連載
» 2003年12月10日 10時00分 UPDATE

XMLテクニック集(8):XML SchemaでXML文書の妥当性を検証する (3/3)

[山田祥寛,@IT]
前のページへ 1|2|3       

document関数で細分化されたXML文書を結合する

アイコン

実体参照を使わずに複数のXML文書を結合するには、XPathのdocument関数を使って外部のXMLファイルを取り込みます。この方法の利点は、取り込みの際にフィルタリング処理を加えられることです。

カテゴリ XPath
関連要素 document
関連記事 実体参照宣言を利用して、XML文書を分割管理する

 別稿「実体参照宣言を利用して、XML文書を分割管理する」では、分割されたXML文書をDTD実体参照)を利用して結合する方法を紹介しました。XML文書を分割することによるメンテナンスのしやすさ、ドキュメントの再利用性といったメリットは、そちらでも述べたとおりです。

 しかし、実体参照による結合は手軽ではあるものの、柔軟性という意味ではいまいちです。というのも、固定的に記述された実体参照はあくまで「静的な」記述であるため、必ず一度はすべてのデータを取り込まなければなりません。取り込みの際にある条件で抽出を行うような絞り込みはできないのです(表示時にはXSLTでフィルタリングを行うにせよ、それはあくまで一度は結合した後の処理です)。

 しかし、本稿のテクニックを用いることで、より柔軟な分割データの処理が可能になります。まずは具体的なサンプルを見てみましょう。サンプルは、取り込むXML文書の一覧を示したインデックスXML(books.xml)、個別のデータ本体を記述したbookX.xml(Xは連番)、そして取り込んだデータを表示するためのXSLTスタイルシート(tabl.xsl)から構成されます。サンプルを試す場合には、books.xmlから起動できます。

[books.xml]

<?xml version="1.0" encoding="Shift_JIS" ?>
<?xml-stylesheet type="text/xsl" href="table.xsl" ?>
<books name="書籍情報一覧">
  <book href="book1.xml" />
  <book href="book2.xml" />
  <book href="book3.xml" />
  <book href="book4.xml" />
  <book href="book5.xml" />
</books>

[book1.xml](book2〜5.xmlは同様の構成であるため省略)

<?xml version="1.0" encoding="Shift_JIS" ?>
<book isbn="ISBN4-7981-0189-3">
  <title>10日でおぼえるJSP/サーブレット入門教室</title>
  <author>Y.Yamada</author>
  <published>翔泳社</published>
  <price>2800</price>
  <publishDate>2002/05/17</publishDate>
  <description>サーバサイド技術の雄「<keywd>JSP/サーブレット</keywd>」をJava初心者でもわかる10日間のセミナー形式で紹介。</description>
</book>

[table.xsl]

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 version="1.0">
  <xsl:template match="/">
    <html>
    <head>
    <title><xsl:value-of select="books/@name" /></title>
    </head>
    <body >
    <h1><xsl:value-of select="books/@name" /></h1>
    <table border="1">
    <tr>
      <th>ISBNコード</th><th>書名</th><th>著者</th>
      <th>出版社</th><th>価格</th><th>発刊日</th>
    </tr>
    <xsl:for-each select="document(books/book/@href)/book">
      <xsl:sort select="published"
                data-type="text" order="descending" />
      <xsl:sort select="price"
                data-type="text" order="ascending" />
      <tr>
        <td nowrap="nowrap">
          <xsl:value-of select="@isbn" /></td>
        <td nowrap="nowrap">
          <xsl:value-of select="title" /></td>
        <td nowrap="nowrap">
          <xsl:value-of select="author" /></td>
        <td nowrap="nowrap">
          <xsl:value-of select="published" /></td>
        <td nowrap="nowrap">
          <xsl:value-of select="price" /></td>
        <td nowrap="nowrap">
          <xsl:value-of select="publishDate" /></td>
      </tr>
    </xsl:for-each>
    </table>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>


図 books1〜5.xmlの内容を一覧表示 図 books1〜5.xmlの内容を一覧表示(クリックで拡大します)

 ポイントとなるのは、以下の部分です。

<xsl:for-each select="document(books/book/@href)/book">
  ……略……
</xsl:for-each>


 document関数は、XPath関数の中でもノードセット関数に分類される関数の1つで、引数に指定されたパスに合致するノード値をキーに、外部のXML文書を呼び出します。つまり、ここでは<book>要素のhref属性(books.xml)に示されたbookX.xmlを順に呼び出し、その配下の<book>要素について繰り返し処理を行うことを意味します。

 ここでは、books.xmlに書かれているものをすべて出力していますが、出力するものとしないものを分けて抽出することも可能です。この場合、books.xmlの各<book>要素にflag属性を追加し、出力したいものにtrue、出力したくないものにfalseと指定します。そのうえで、table.xslの<xsl:for-each>要素を以下のように書き換えます。

<xsl:for-each
 select="document(books/book[@flag='true']/@href)/book">


 すると、flag属性がtrueである文書のみが取り込まれ、一覧表示されます。flag属性がfalseであるものは取り込みそのものが行われませんから、flag属性がfalseである文書が多くなったとしても、処理パフォーマンスが低下することはありません。

前のページへ 1|2|3       

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。