XSLT3.0への道(3) 訂正 xsl:evaluate

すみません.xsl:evaluateの記述と例は誤りがありました.
 
> xsl:evaluateの@xpathからは、xsl:variableやxsl:paramを参照することができないとされています.
> 参照するには、xsl:evaluateの下位要素のxsl:with-paramを使います.
 
は、誤りです.@xpathの中からは、スコープ内のxsl:variableやxsl:paramを参照できます.ですからスタイルシートは、xsl:with-paramなしの以下で問題なく動作します.@xpathは"/data/product[@type= 'note']"となります.
 
<?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,''']')"/>
      </output>
  </xsl:template>
</xsl:stylesheet>
 
ではxsl:evaluateの子要素のxsl:with-paramはどう使うのでしょうか?これは@xpathXPath式として評価されたとき変数として記述されたものとのインターフェースを取るのに使われます.
ですから、以下のようなxsl:evaluateの@xpathの記述の場合はxsl:with-paramが必要です.@xpathは"/data/product[@type= $prmAtrValue]"となり、$prmAtrValueを参照するからです.
 
<?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="prmAtrValue" as="xs:string" select="$prmAtrValue"/>
          </xsl:evaluate>
      </output>
  </xsl:template>
</xsl:stylesheet>
 
また、次のスタイルシートも誤りがありました.
 
>ところでSaxon9.3のインプリメントにはまだバグがあるようで、
>次のようにxsl:eveluateでXPathの動的エラーを発生させてみようと思いましたが、
>NPE(Null Pointer Exception)でこけてしまいました.
 
現在のSaxon PE 9.3.0.4jにバグがあるのは確かです.これはとりあえずxsl:evaluateの@base-uriに影響のない適当な値をセットすれば回避できるとのこと.問題はxsl:evaluateの@xpathXPath式は、そのときのカレントコンテキストで解釈されるということです.このため<xsl:template match="/">のコンテキストでxsl:evaluateが動くようにしてやらなければなりません.このためもう一個xsl:for-eachを追加する必要があります.
 
<?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"
 xmlns:err="http://www.w3.org/2005/xqt-errors"
 exclude-result-prefixes="xs err"
>
  <xsl:output indent="yes"/>
  <xsl:param name="prmXPathFile" as="xs:string" select="'xpath.xml'"/>
  <xsl:template match="/">
      <xsl:variable name="currentNode" select="." as="document-node()"/>
      <output>
          <xsl:for-each select="doc($prmXPathFile)//xpath">
              <xsl:variable name="xPath" select="string(.)" as="xs:string"/>
              <xsl:message select="'XPath=',$xPath"/>
              <xsl:try>
                  <xsl:for-each select="$currentNode">
                      <xsl:evaluate xpath="$xPath" base-uri="http://www.w3.org/1999/XSL/Transform"/>
                  </xsl:for-each>
                  <xsl:catch>
                      <xsl:message terminate="yes" select="'XPath evaluation failed: Error code:', $err:code, 'Reason:', $err:description"/>
                  </xsl:catch>
              </xsl:try>
          </xsl:for-each>
    </output>
  </xsl:template>
</xsl:stylesheet>
 
このスタイルシートは、xpath.xmlに記述したXPath式が正しければ動作します.次のようにxpath.xmlに誤ったXPath式を記述した場合、
 
<xpath>//data/1/product[string(@type) eq 'other']</xpath>
 
実行結果は以下のようになります.xsl:try, xsl:catchが動作しているのを確認できます.
 
XPath= //data/product[string(@type) eq 'pencil']
XPath= //data/product[string(@type) eq 'note'][string(@unitPrice) eq '150']
XPath= //data/1/product[string(@type) eq 'other']
Warning: Required item type of first operand of '/' is node(); supplied value has item type xs:integer. The expression can succeed only if the supplied value is an empty sequence.
Warning: The only value that can pass type-checking is an empty sequence. Required item type of   first operand of '/' is node(); supplied value has item type xs:integer
XPath evaluation failed: Error code: err:XPTY0019 Reason: Required item type of first operand of '/' is node(); supplied value has item type xs:integer
Processing terminated by xsl:message at line 21 in style.xsl
以上 失礼しました.