XMLを学習する2(XHTML基本編)
XML学習2回目。誰得という意見は認める。今回は実践編でコードがいっぱい出てきます。だから前回よりも大分読みやすいと思います。前回:XMLを学習する1(理論編) - たぬきのねどこ
今回はhttp://www6.airnet.ne.jp/manyo/xml/というサイトの「XMLをIEで表示(基礎編-1)」を参考にXMLを実践的に学びました。若干目的と違うことになり、何故かXHTMLの基本を学んでしまいましたが、まぁいいや。なんとなくXMLの基本が分かった気もするし。例の如く、以下は興味のある方だけ「続きを読む」でどうぞ。次こそは、分からないままGoogleガジェット作って貼りたい。
Hello World!(1−7)
実践の最初と言えばHello Worldですよね。上側のスクリプトをhello.xml、下側のスクリプトをhello.xslとして保存します。hello.xmlに書かれているデータを、stylesheetであるhello.xslに書かれている文法で表示する、ということですよね。xmlはデータファイルと文法ファイルになると考えればいいみたい。データファイルの方の2行目、「xml:stylesheet type="text/xsl" href="hello.xsl"」で文法ファイル(xsl)を指定しています。うん、分かりやすい。しかしこの男は上から目線過ぎてムカつく。
<?xml version="1.0" encoding="ISO-2022-JP" ?> <?xml:stylesheet type="text/xsl" href="hello.xsl" ?> <文書> <タイトル>題名</タイトル> <内容>HelloWorld</内容> </文書>
<?xml version="1.0" encoding="ISO-2022-JP" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html lang="ja"> <head> <title><xsl:value-of select="/文書/タイトル"/></title> </head> <body> <h2><xsl:value-of select="/文書/内容"/></h2> </body> </html> </xsl:template> </xsl:stylesheet>
んで、問題のスタイルシートの方なのですが。2行目のURLは名前空間ですね、前回やりました。value-ofというのはデータファイルからデータを取り出すものなのか。ただtemplateの意味がよく分からない……。
templateってなに?(8-11)
こちらの文書にわかりやすく書いてありました(※pdfファイルです)。31p目あたりから。template match="xxx"のxxxに当たるものがXML内にあれば、templateの内容を適用する、ということですね。だから、match="/"のtemplateに文書全体の形式を書いて(htmlなど)、更に細かいところは他のtemplateで置き換えると。つまり、XSLはtemplateの集まりなんですね。なるほど。
template match="/"でHTMLに変換された後、更に細かいtemplateを使いたい場合には、xsl:apply-templatesを突っ込んでやれば良い、とのこと。ん?match="/"以外のtemplateが複数あったらどう処理されるんだ?疑問はあるものの、とりあえず練習がてら作ってみる。(後述の「複数のtemplateを使う(18)」で解決)
<?xml version="1.0" encoding="ISO-2022-JP" ?> <?xml:stylesheet type="text/xsl" href="test.xsl" ?> <リスト> <本 ID="1"> <タイトル>覘き小平次</タイトル><著者>京極夏彦</著者><出版>講談社</出版> </本> <本 ID="2"> <タイトル>徹底抗戦</タイトル><著者>ホリエモン</著者><出版>集英社</出版> </本> <本 ID="3"> <タイトル>スカイ・クロラ</タイトル><著者>森博嗣</著者><出版>中央公論</出版> </本> </リスト>
<?xml version="1.0" encoding="ISO-2022-JP" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html lang="ja"> <body> <table border="4"><xsl:apply-templates /></table> </body> </html> </xsl:template> <xsl:template match="本"> <tr> <td><xsl:value-of select="タイトル" /></td> <td><xsl:value-of select="著者" /></td> </tr> </xsl:template> </xsl:stylesheet>
xml:value-of select="xxx"はOKなんだけど、imageはxml:attributeで書くらしい。確かにimgのsrc属性を書くだけだから、いきなりvalue-ofだとマズいわけか。ふぅん。
XMLの内容によって違う内容表示(12−17)
段々と面白そうなことが出てきた。XMLの要素によって、生成される文書が異なるようにXSLを書くとのこと。さっきのXMLで集英社出版のものだけ弾いてみよう。XMLデータファイルはさっきのままで、XSL後半のtemplateを以下のように変更します。when testのところは、"出版[.='集英社']"という書き方もあるみたい。これは名前空間に準拠するようだ。
<xsl:template match="本"> <xsl:choose> <xsl:when test="出版 = '集英社' "/> <xsl:otherwise> <tr> <td><xsl:value-of select="タイトル" /></td> <td><xsl:value-of select="著者" /></td> </tr> </xsl:otherwise> </xsl:choose> </xsl:template>
15の属性の話。HTMLの属性をXSLで突っ込みたい場合はxsl:attribute name="xxx"で突っ込む。XMLデータファイルの属性を取ってきてXSLで扱いたい場合は@xxxという名前で扱う。
16になって衝撃の事実が。さららって持統天皇だったのか……。xml:ifが出てきた。どうもxml:chooseはSWITCH構文みたいなものだったらしい。算術演算子が出てきたので、本のIDが偶数のものだけ取り出してみよう。このmodとか算術記号も名前空間準拠。
<xsl:template match="本"> <xsl:if test="(@ID mod 2)=0"> <tr> <td><xsl:value-of select="タイトル" /></td> <td><xsl:value-of select="著者" /></td> </tr> </xsl:if> </xsl:template>
複数のtemplateを扱う(18)
以前疑問だった、templateを複数使う方法について。templateとapply-templateにそれぞれmode属性を持たせればいいらしい。保守の観点からいうと、毎回持たせた方がいいのかな。
<?xml version="1.0" encoding="ISO-2022-JP" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html lang="ja"> <body> <p>タイトル羅列:<xsl:apply-templates select="リスト/本" mode="あ"/></p> <p>出版社羅列:<xsl:apply-templates select="リスト/本" mode="い"/></p> </body> </html> </xsl:template> <xsl:template match="本" mode="あ"> <xsl:value-of select="タイトル" />, </xsl:template> <xsl:template match="本" mode="い"> <xsl:value-of select="出版"/>, </xsl:template> </xsl:stylesheet>
for-eachとかsortとか(19−20)
まぁ、簡単で便利。
<?xml version="1.0" encoding="ISO-2022-JP" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html lang="ja"> <body> <p>ソート前: <xsl:apply-templates select="リスト" mode="そのまま"/></p> <p>ソート後: <xsl:apply-templates select="リスト" mode="ソート"/></p> </body> </html> </xsl:template> <xsl:template match="リスト" mode="そのまま"> <xsl:for-each select="本"> <xsl:value-of select="タイトル"/>、 </xsl:for-each> </xsl:template> <xsl:template match="リスト" mode="ソート"> <xsl:for-each select="本"> <xsl:sort select="著者" /> <xsl:value-of select="タイトル"/>、 </xsl:for-each> </xsl:template> </xsl:stylesheet>
21と22も簡単なので飛ばします。23−24では変数を扱う。xsl:variableの属性としてname="変数名"とselect="内容"と記述すればいいわけだ。S変数名で呼び出し。あとはconcatとかで繋げてやればいい。変数への代入が出来るなら色々作れるけど、まだ出てこないので飛ばします。
テンプレートに変数を渡す。関数的なテンプレート(25−26)
call-templateで、属性nameをつけたtemplateが呼び出せる。これを利用すると、ちょっとした関数的なものを作れる。以下のは0から10までの数値を書くXSL。XMLデータの内容を必要としないのはちょっと面白いかな。
<?xml version="1.0" encoding="ISO-2022-JP" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html lang="ja"> <body> <p><xsl:call-template name="十まで数える" /></p> </body> </html> </xsl:template> <xsl:template match="/" mode="null" name="十まで数える"> <xsl:param name="i">0</xsl:param> <xsl:choose> <xsl:when test='$i="10"'>10</xsl:when> <xsl:otherwise> <xsl:value-of select="$i"/><!-- iが幾つかを表記 --> <xsl:call-template name="十まで数える"> <xsl:with-param name="i" select="$i+1"/><!--i+1で再帰させる--> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
複数パラメータは渡せないのか、パラメータへの代入は出来ないのか、など疑問が浮かぶ。どうも代入は出来ないみたいだなぁ……