XMLを学習する2(XHTML基本編)

XML学習2回目。誰得という意見は認める。今回は実践編でコードがいっぱい出てきます。だから前回よりも大分読みやすいと思います。前回:XMLを学習する1(理論編) - たぬきのねどこ
今回はhttp://www6.airnet.ne.jp/manyo/xml/というサイトの「XMLIEで表示(基礎編-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>

複数パラメータは渡せないのか、パラメータへの代入は出来ないのか、など疑問が浮かぶ。どうも代入は出来ないみたいだなぁ……

そのあと

CSVの話とかが書いてありますが、この辺でやっとGoogleガジェット作りに関係ないことに気付いた。でも、いいんです。なんとなくXMLってこんなものってことが学べたので。明日こそGoogleガジェット作りをしたいなぁ。とりあえず、昨日今日で学んだことで何か作ってみる。