連載
» 2003年08月20日 10時00分 公開

XMLテクニック集(4):多階層のXML文書にナンバリング処理を行う (2/3)

[山田祥寛,@IT]

フラットな階層のXML文書で階層的なナンバリング処理

アイコン

XML文書としては階層を持たず、代わりに属性で階層を表しているような文書でも階層的なナンバリングを実現できます。<xsl:template>の適用で少し凝ったテクニックを使用します。

カテゴリ XSLT
関連要素 <xsl:number>
関連記事 多階層のXML文書にナンバリング処理を行う

 あらかじめ多階層構造のXML文書に対して、階層を意識したナンバリング処理を行う方法は「多階層のXML文書にナンバリング処理を行う」でご紹介しています。しかし、以下のcontents2.xmlのように、XML文書自体はフラットな構造になっている場合はどのようにしたらよいでしょう。

[contents2.xml]
<?xml version="1.0" encoding="Shift_JIS" ?>
<?xml-stylesheet type="text/xsl" href="contents2.xsl" ?>
<book title="10日でおぼえるJakarta入門教室">
  <section class="1" title="オリエンテーション" />
  <section class="2" title="Jakartaの基礎知識" />
  <section class="2" title="Windowsにおける環境設定の方法" />
  <section class="2" title="Linuxにおける環境設定の方法" />
  <section class="1" title="JSP/サーブレットの基本を学ぶ" />
  <section class="2" title="JSPの基本を学ぼう" />
  <section class="2" title="サーブレットの基本を学ぼう" />
  <section class="2" title="JavaBeansの基本を学ぼう" />
  <section class="1" title="Strutsの基本構成を学ぶ" />
  <section class="2" title="Strutsからあなたに「こんにちは」" />
  <section class="2" title="「Struts」から「ストラッツ」に" />
  <section class="1" title="Strutsで簡単アプリケーションを作成する" />
  <section class="2" title="ActionFormBeansでフォームを制御する" />
  <section class="2" title="ActionFormBeansでデータ検証を行う" />
</book>

 「多階層のXML文書にナンバリング処理を行う」のcontents.xmlと比較してみてください。XML文書それ自体としての階層構造はなくなり、代わりに階層レベルが各<section>要素のclass属性で表されています(class="1"は章、class="2"は節)。

(1)class属性で指定された階層構造に対応する

 このようなXML文書に対して、階層を加味したナンバリングを行うためには、テンプレート適用の局面でちょっとした工夫を凝らす必要があります。

[contents2.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="book/@title" /></title>
    </head>
    <body>
    <xsl:for-each select="book/section">
      <xsl:apply-templates select="." />
    </xsl:for-each>
    </body>
    </html>
  </xsl:template>
  <xsl:template match="section[@class='1']">
    <div>
      <xsl:number level="any" count="section[@class='1']" />.
      <xsl:value-of select="@title" />
    </div>
  </xsl:template>
  <xsl:template match="section[@class='2']">
    <div>
      <xsl:number level="any" count="section[@class='1']" />.
      <xsl:number level="any" from ="section[@class='1']"
                              count="section[@class='2']" />.
      <xsl:value-of select="@title" />
    </div>
  </xsl:template>
< /xsl:stylesheet>
class属性に対応したナンバリングが施された class属性に対応したナンバリングが施された

 1階層目の<section>要素に対して適用されるテンプレート(<xsl:template>要素)は以下の部分です。

<xsl:template match="section[@class='1']">
  <div>
    <xsl:number level="any" count="section[@class='1']" />.
    <xsl:value-of select="@title" />
  </div>
</xsl:template>

 <xsl:number>要素のlevel属性が“any”である場合、count属性に合致した要素について、通し番号が振られます。つまり、ここでは<section>要素のclass属性が“1”であるものについて、ナンバリングを行います。

(2)節番号の開始時にリセットする指定

 次に、2階層目を意味する<section>要素に対して適用されるテンプレートです。

<xsl:template match="section[@class='2']">
  <div>
    <xsl:number level="any" count="section[@class='1']" />.
    <xsl:number level="any" from ="section[@class='1']"
                            count="section[@class='2']" />.
    <xsl:value-of select="@title" />
  </div>
</xsl:template>

 2つの<xsl:number>要素に注目してください。1つ目の<xsl:number>要素は上記同様、1階層目の<section>要素についてカウントします。

 問題は2つ目の<xsl:number>要素です。from属性として "section[@class='1']" が指定されていることに注目してください。fromは「どこからナンバリングを開始するか」を指定するための属性です。つまり、<section class="2">をナンバリングするに際しては、<section class="1">要素が登場するごとにナンバをリセットし、そこから再度ナンバリングを開始するというわけです。これによって、章ごとに節がナンバリングされるのです。

 <xsl:number>要素には属性も多く登場し、XSLTの中でもなかなか分かりにくい要素の1つですが、使いこなせば、非常に使い勝手のある要素でもあります。XML文書の構造を変えたり(階層を増やすなど)、<xsl:number>要素の属性値を変更したりして、どのように表示が変化するかを自分で試してみると、きっと面白い発見があるはずです。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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