会社で開発用にSaxonをバージョンアップしました.Professional Edition (PE)ですが、XSLT3.0の機能の一部が使えます.せっかくXSLT3.0のワーキングドラフトも出ていることなので、少しXSLT3.0の例を紹介したいと思います.ただし、あくまでもW3Cのワーキングドラフトに基づいていますので、これが正式なXSLT3.0勧告(Recommendation)になる保障はありません.この点ご了解願います.
[入力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"?>
<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 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 version="1.0" encoding="UTF-8"?>
<foo>
<out>
<wibble>test text 1</wibble>
</out>
<out>
<wibble>Another wibble </wibble>
</out>
<out att="value1"/>
</foo>
では、スタイルシートのパラメータに属性名や属性値を指定して結果を得るのにはどうしたら良いのでしょう?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" ?>
<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>
<?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
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>
<?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のスレッドを参照ください.