2

元のXMLに追加のノードを挿入するxsl:templateがあります。

次に、次のテンプレートを使用して、その新しいノードを参照し、ソースファイルの解析の継続を支援したいと思います。

私の現在のメソッド(2番目のテンプレート)は、最初のテンプレートから新しく挿入されたノードを「認識」しません。これにどのようにアプローチしますか?

どうもありがとう。

以下の例は、私が達成しようとしていることを表現するために非常に単純化されています。

XMLの開始:

<master> 
 <node>
  <node1>hi</node1>
  <node2>bye</node2>
 </node>
</master>

最初のテンプレート:

<xsl:template match="master/node">
  <node>
  <xsl:apply-templates/>
  <node3>greetings</node3>
  </node>
</xsl:template>

結果XML1:

<master> 
 <node>
  <node1>hi</node1>
  <node2>bye</node2>
  <node3>greetings<node3>
 </node>
</master>

2番目のテンプレート:

<xsl:template match="master/node[node3='greetings']">
  <node>
   <newnode><xsl:value-of select="./node3"/>
  </node>
</xsl:template>

期待される結果:

<master> 
 <node>
  <newnode>greetings</newnode>
 </node>
</master>

XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

        <!-- first template -->
<xsl:template match="master/node">
  <node>
  <xsl:apply-templates/>
  <node3>greetings</node3>
  </node>
</xsl:template>

        <!-- second template -->
<xsl:template match="master/node[node3='greetings']">
  <node>
   <newnode><xsl:value-of select="./node3"/></newnode>
  </node>
</xsl:template>

4

3 に答える 3

3

拡張機能のないXSLT1.0では、入力ドキュメント内のノードのみをテンプレートと照合できます。テンプレートを中間結果に適用するには、nodeset拡張機能(XSLT 1.0実装によって広く実装されている)を使用して、テンプレートを結果ツリーフラグメントに適用できるようにします。または、XSLT2.0に移行することもできます。

ノードセット拡張の詳細については、関連する質問に対するDimitreNovatchevの回答を参照してください。

于 2012-09-11T01:57:55.610 に答える
1

Michael Sperberg-McQueenは、XSLT 1.0でRTF(結果ツリーフラグメント)を処理する方法を正確に説明しています。

EXSLTnode-set()拡張機能を使用した完全なソリューションの例を次に示します。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
   <xsl:apply-templates/>
  </xsl:variable>
  <xsl:apply-templates select="ext:node-set($vrtfPass1)/*"/>
 </xsl:template>

 <xsl:template match="master/node">
  <node>
   <xsl:apply-templates/>
   <node3>greetings</node3>
  </node>
 </xsl:template>

 <xsl:template match="master/node[node3='greetings']" priority="2">
  <node>
   <newnode><xsl:value-of select="./node3"/></newnode>
  </node>
 </xsl:template>
</xsl:stylesheet>

この変換が提供されたXMLドキュメントに適用される場合:

<master>
 <node>
  <node1>hi</node1>
  <node2>bye</node2>
 </node>
</master>

必要な正しい結果が生成されます。

<master>
   <node>
      <newnode>greetings</newnode>
   </node>
</master>

Pass-Nで動作するすべてのテンプレートが、他のパス番号で動作するすべてのテンプレートとは別の異なるモードになるように、マルチパス処理を編成するのが最善であることに注意してください。これは、Pass-NとPass-Mの両方で実行するために同じテンプレートが誤って選択された場合のエラーを回避するためです。

モードを使用すると、上記のソリューションは次のようになります。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

  <xsl:template match="node()|@*" mode="pass2">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*" mode="pass2"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
   <xsl:apply-templates/>
  </xsl:variable>
  <xsl:apply-templates mode="pass2"
  select="ext:node-set($vrtfPass1)/*"/>
 </xsl:template>

 <xsl:template match="master/node">
  <node>
   <xsl:apply-templates/>
   <node3>greetings</node3>
  </node>
 </xsl:template>

 <xsl:template mode="pass2" match="master/node[node3='greetings']"
      priority="2">
  <node>
   <newnode><xsl:value-of select="./node3"/></newnode>
  </node>
 </xsl:template>
</xsl:stylesheet>
于 2012-09-11T04:19:39.063 に答える
1

XSLT 2.0では、変数の最初のテンプレートの出力をキャプチャするだけで、変数の値は、ソースドキュメントと同じように処理できる新しいXMLドキュメントです。

XSLT 1.0では、テンプレートの出力を変数にキャプチャすると、それはファーストクラスのドキュメントではなく、非常に限られた方法でしか処理できない「結果ツリーフラグメント」になります。exslt:node-set()拡張機能は、それを「結果ツリーフラグメント」から、通常どおり処理できるファーストクラスのドキュメントに変換します。

これが、他の人から提供された非常に詳細な情報を要約するのに役立つことを願っています(最近は、特に指示がない限り、XSLT 2.0を使用していると想定する必要があります)。

于 2012-09-11T08:02:54.700 に答える