XSLT3.0への道(1) xsl:evaluate

会社で開発用にSaxonをバージョンアップしました.Professional Edition (PE)ですが、XSLT3.0の機能の一部が使えます.せっかくXSLT3.0のワーキングドラフトも出ていることなので、少しXSLT3.0の例を紹介したいと思います.ただし、あくまでもW3Cのワーキングドラフトに基づいていますので、これが正式なXSLT3.0勧告(Recommendation)になる保障はありません.この点ご了解願います.
 
最初はxsl:evaluateです.この要素は、xpath属性をXPath式として評価して結果を返してくれます.次の例はかつてxsl-listに投稿されていたものを若干修正したものです.
 
[入力XML
<?xml version="1.0" encoding="UTF-8"?>
<foo>
    <paths>
        <path>/foo/blort/wibble[1]</path>
        <path>/foo/blort/wibble[2]</path>
         <path>//*[@xml:id='wibNum2']/splat/@att</path>
    </paths>
    <blort>
        <wibble>test text 1</wibble>
        <wibble>Another wibble </wibble>
        <wibble xml:id="wibNum2">This is <splat att="value1">a
test</splat></wibble>
    </blort>
</foo>
 
[スタイルシート]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/foo">
    <foo>
        <xsl:for-each select="paths/path">
          <out>
            <xsl:evaluate xpath="."/>
          </out>
        </xsl:for-each>
    </foo>
</xsl:template>
</xsl:stylesheet>
 
[結果XML]
<?xml version="1.0" encoding="UTF-8"?>
<foo>
   <out>
      <wibble>test text 1</wibble>
   </out>
   <out>
      <wibble>Another wibble </wibble>
   </out>
   <out att="value1"/>
</foo>
 
入力XML中に記述されたXPath式を使って、結果XMLを作ることができます.
では、スタイルシートのパラメータに属性名や属性値を指定して結果を得るのにはどうしたら良いのでしょう?xsl:evaluateの@xpathからは、xsl:variableやxsl:paramを参照することができないとされています.参照するには、xsl:evaluateの下位要素のxsl:with-paramを使います.
 
# 上記記述とスタイルシート例には誤りがあります.XSLT3.0への道(3) 訂正 xsl:evaluate を参照ください.(2011/02/26)
 
[input.xml]
<?xml version="1.0" encoding="UTF-8" ?>
<data>
    <product type="pencil" maker="三菱"     unitPrice="100"/>
    <product type="pencil" maker="コーリン" unitPrice="90"/>
    <product type="pencil" maker="トンボ"   unitPrice="110"/>
    <product type="pencil" maker="北星"     unitPrice="105"/>
    <product type="note"   maker="コクヨ"   unitPrice="200"/>
    <product type="note"   maker="ツバメ"   unitPrice="180"/>
    <product type="note"   maker="マルマン" unitPrice="150"/>
</data>
 
[スタイルシート]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 exclude-result-prefixes="xs">
<xsl:output indent="yes"/>
<xsl:param name="prmAtrName"  as="xs:string"/>
<xsl:param name="prmAtrValue" as="xs:string"/>
<xsl:template match="/">
    <output>
        <xsl:evaluate xpath="concat('/data/product[',$prmAtrName, ' = ''', $prmAtrValue,''']')">
            <xsl:with-param name="prmAtrName"  as="xs:string" select="$prmAtrName"/>
            <xsl:with-param name="prmAtrValue" as="xs:string" select="$prmAtrValue"/>
        </xsl:evaluate>
    </output>
</xsl:template>
</xsl:stylesheet>
 
[コマンドライン]
java net.sf.saxon.Transform -o:result.xml -s:input.xml -xsl:style.xsl prmAtrName=@type prmAtrValue=note
 
[result.xml]
<?xml version="1.0" encoding="UTF-8"?>
<output>
   <product type="note" maker="コクヨ" unitPrice="200"/>
   <product type="note" maker="ツバメ" unitPrice="180"/>
   <product type="note" maker="マルマン" unitPrice="150"/>
</output>
 
いかがでしょうか?ちゃんとスタイルシートのパラメータに指定した属性名と属性値で結果を作成できました.xsl:evaluateはこのように、XPath式を外部から与えることができるので、今までにないXSLTの使い方ができるようになります.
 
しかし、このxsl:evaluateの機能「XPathの動的評価」には、様々な意見もあるようです.この機能を実装するとすれば、XSLTプロセッサは必ず実行時にXPathを評価できなければなりません.コンパイル済みのスタイルシートという訳にはゆかなくなります.
 
興味のある方は以下のxsl-listのスレッドを参照ください.