3

呼び出し元のノードへのxpathを返すXSLT関数が必要です。

XML

    <root>
      <node>
        <subnode />
        <subnode />
        <subnode />
      </node>
      <node>
        <subnode>
          <subsubnode >
            <xsl:value-of select="fn:generateXPath()" />
          </subsubnode >
        </subnode>
      </node>
    </root>

XSL

    <xsl:template match="root/node/subnode/sub" >
        <xsl:value-of select="fn:generateXPath()" />
    </xsl:template>

    <xsl:function name="fn:generateXPath" >
      <xsl:for-each select="ancestor::*">
      <xsl:value-of select="name()" />
      </xsl:for-each>
      <xsl:value-of select="name()" /> 
    </xsl:function>

上記の関数を試してみましたが、エラーが発生します。

XPDY0002:ここでノードを選択できません:コンテキストアイテムが未定義です

しかし、名前付きテンプレートでこれを試したところ、結果を得ることができました。これは、を使用して実装できますかxslt:function

4

2 に答える 2

7

上記の関数を試してみましたが、エラーが発生します。

XPDY0002: Cannot select a node here: the context item is undefined

しかし、名前付きテンプレートでこれを試したところ、結果を得ることができました。

W3C XSLT 2.0仕様によると:

スタイルシート関数の本体内では、フォーカスは最初は未定義です。これは、コンテキストアイテム、コンテキスト位置、またはコンテキストサイズを参照しようとすると、回復不可能な動的エラーになることを意味します。[XPDY0002]」

あなたのコードでは:

<xsl:function name="fn:generateXPath" >    
  <xsl:for-each select="ancestor::*">    
  <xsl:value-of select="name()" />    
  </xsl:for-each>    
  <xsl:value-of select="name()" />     
</xsl:function>    

コンテキストアイテム(フォーカス、現在のノード)に対してのみ評価できる相対式がいくつかありますが、定義によって定義されたものはないため(上記の引用を参照)、報告されたエラーが発生します。

解決策

この関数のパラメーターを追加します。これがノード、つまり必要なものを選択するためのXPathになるのは当然です。

<xsl:function name="fn:generateXPath" as="xs:string" >
  <xsl:param name="pNode" as="node()"/>

  <xsl:for-each select="$pNode/ancestor::*">    
    <xsl:value-of select="name()" />    
  </xsl:for-each>    
  <xsl:value-of select="name($pNode)" />     
</xsl:function>    

この関数を次のように呼び出します。

fn:generateXPath(someNode)

:明らかに、述語内の位置を使用して、各名前を文字に連結し、ノ​​ード"/"の兄弟を選択しないように式を絞り込む必要があります。ノードのXPath式を作成する完全で正しいソリューションについては、この質問に対する私の回答を参照してください:https ://stackoverflow.com/a/4747858/36305

于 2011-12-14T13:17:57.150 に答える
6

標準機能がない理由の1つは、さまざまな理由でパスが必要なことです。

時にはa/b/c/d十分です。

一部の人々はしたいですa[3]/b[5]/c[1]/d[2]

名前に名前空間プレフィックスが含まれていないパスが必要な場合は、次のようにする必要があります。

*:a[namespace-uri()='abc']/*:b[namespace-uri='xyz']

于 2011-12-14T15:20:34.083 に答える