2017-10-07 5 views
2

thisによると、matchのXPath式のパラメータを使用することは可能です。しかし、xsl:templatexsl:paramが同じテンプレート内で使用される場合は動作しないようです。XSLT 2.0の一致するXPath式でテンプレートパラメータを使用することはできませんか?

<?xml version="1.0" encoding="UTF-8"?> 
<myRoot> 
    <myNode myAttribute="3"> 
     <myChildAttribute myChildAttribute="a" /> 
    </myNode> 
    <myNode myAttribute="2"> 
     <myChildAttribute myChildAttribute="b" /> 
    </myNode> 
    <myNode myAttribute="1" /> 
</myRoot> 

、そのような私のXSLファイルを次のように

私のXMLファイルが見えます。 SAXON 9HEを実行したとき

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" encoding="UTF-8"/> 

    <xsl:template match="myRoot"> 
     <xsl:apply-templates select="myNode"> 
      <xsl:sort select="@myAttribute" /> 
      <xsl:with-param name="myParam" select="max(myNode/@myAttribute)" /> 
     </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="myNode[node() and @myAttribute = $myParam]"> 
     <xsl:param name="myParam" /> 
      <xsl:for-each select="myChildAttribute"> 
INSERT INTO a(b) VALUES ('<xsl:value-of select="@myChildAttribute" />'); 
      </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

は、残念ながら同じテンプレートのマッチXPath式では、テンプレートのパラメータを使用することはできません、次のエラー

XPST0008: Variable myParam has not been declared (or its declaration is not in scope) 

で終わります! ?

答えて

3

同じテンプレートの に一致するXPath式では、テンプレートのパラメータを使用できません。

いいえ、実行のためにテンプレートが選択されている場合、テンプレートの一致式内の変数/パラメータはすべて有効範囲(定義済み/表示可能)でなければなりません。

テンプレートは(グローバルレベルで定義された)XSLTディレクティブなので、スコープ内にある変数/パラメータはグローバルレベルの変数/パラメータのみです。

テンプレートのパラメータは、テンプレートが実行前に選択された後にのみ渡されます。つまり、このパラメータの値は、テンプレート選択プロセスが実行されているときには存在しません。

非大域発現は、実行プロセスのためのテンプレートの選択に使用する場合したがって、それは、この式を評価することができる対応xsl:apply-templates命令のselect属性に供給する必要がある - ないでmatchテンプレートの属性。この式は評価できません。

これを明確にするために、以下のコードが提供されたコードに問題を修正します。

<myRoot> 
    <myNode myAttribute="3"> 
     <myChildAttribute myChildAttribute="a" /> 
    </myNode> 
    <myNode myAttribute="2"> 
     <myChildAttribute myChildAttribute="b" /> 
    </myNode> 
    <myNode myAttribute="1" /> 
</myRoot> 

:この変換が提供されるXML文書に適用されると

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
     <xsl:output method="text" encoding="UTF-8"/> 

     <xsl:template match="myRoot"> 
      <xsl:apply-templates select="myNode[@myAttribute = max(../myNode/@myAttribute)]"> 
       <xsl:sort select="@myAttribute" /> 
      </xsl:apply-templates> 
     </xsl:template> 

    <xsl:template match="myNode[node()]"> 
      <xsl:for-each select="myChildAttribute"> 
INSERT INTO a(b) VALUES ('<xsl:value-of select="@myChildAttribute" />'); 
      </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

エラーは発生せず、これは変換の出力です(「正しい出力」とは言えません。なぜなら、要件hこれは検証できないためです。そして、私はこのコードに関する私の予約を持っています:例えば、子の使用は、等しい(最大())値をソートし、同じ値のシーケンスの並べ替えが同じシーケンスを生成するので、意味がありません:

INSERT INTO a(b) VALUES ('a'); 
+1

ありがとうDimitre!今私には明らかです。 'xsl:sort'は変換の前のバージョンから残っています。ヒントのおかげで、私はそれを削除します。 – Jagger

2

これはうまくいきません。 paramは、定義したテンプレート内で有効です。ただし、一致式は実際にはテンプレートの一部ではありません。 myParamがまだ定義されていないときは、外部から評価する必要があります。

max(myNode/@ myAttribute)のフィルタをapply-templatesのselect式に移動する必要があります。

関連する問題