2016-07-28 22 views
0

は、私は次のXML持つノード:は、いくつかの次-兄弟を選択するだけ

<xsl:template match="table"> 
<xsl:element name="table"> 
    <xsl:element name="text"> 
    <xsl:apply-templates /> 
    </xsl:element> 
    <xsl:for-each select="following-sibling::foot"> 
    <xsl:element name="foot"> 
    <xsl:apply-templates /> 
    </xsl:element> 
    </xsl:for-each> 
</xsl:element> 
:私は、次のXSLコードを持って

<root> 
<table> 
<text>Table 1</text> 
<foot>1.1</foot> 
<foot>2.2</foot> 
</table> 
<p>...</p> 
<p>...</p> 
<table> 
<text>Table X</text> 
<foot>M.1</foot> 
<foot>M.2</foot> 
</table> 
<p>...</p> 
<p>...</p> 
<table> 
<text>Table 132</text> 
<foot>A.A.E</foot> 
<foot>234</foot> 
</table> 
<p>...</p> 
<p>...</p> 
</root> 

<root> 
<table>Table 1</table> 
<foot>1.1</foot> 
<foot>2.2</foot> 
<p>...</p> 
<p>...</p> 
<table>Table X</table> 
<foot>M.1</foot> 
<foot>M.2</foot> 
<p>...</p> 
<p>...</p> 
<table>Table 132</table> 
<foot>A.A.E</foot> 
<foot>234</foot> 
<p>...</p> 
<p>...</p> 
</root> 

を、私はこれを変換したいです

次のように出力されます。

<root> 
<table> 
<text>Table 1</text> 
<foot>1.1</foot> 
<foot>2.2</foot> 
<foot>M.1</foot> 
<foot>M.2</foot> 
<foot>A.A.E</foot> 
<foot>234</foot> 
</table> 
<p>...</p> 
<p>...</p> 
<table> 
<text>Table X</text> 
<foot>M.1</foot> 
<foot>M.2</foot> 
<foot>A.A.E</foot> 
<foot>234</foot> 
</table> 
<p>...</p> 
<p>...</p> 
<table> 
<text>Table 132</text> 
<foot>A.A.E</foot> 
<foot>234</foot> 
</table> 
<p>...</p> 
<p>...</p> 
</root> 
のみ table要素を閉じるへの即時です foot要素を選択することができますどのように

は、すぐにtable要素を以下foot要素のn数が存在します提供しました。これに関する助けに感謝します。

+0

XSLT 2.0を使用できますか? –

+0

申し訳ありません。 XSLT 2.0は問題ありません。私はそれを指定するべきだった。 – Jagath

答えて

1

これを行う最もきれいな方法は、XSLキーを使用することです。直前<table>の(この回答中の溶液全てXSLTバージョンで動作します。)

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes" /> 

    <xsl:strip-space elements="*" /> 
    <xsl:key name="foot" match="foot" use="generate-id(preceding-sibling::table[1])" /> 

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

    <xsl:template match="table"> 
     <xsl:copy> 
      <text><xsl:apply-templates select="@*|node()"/></text> 
      <xsl:copy-of select="key('foot', generate-id())" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="foot" /> 
</xsl:transform> 

<xsl:key>インデックス一意のIDを使用して文書内のすべての<foot>要素(specを参照)。

<xsl:template match="table">は、同じ固有IDの助けを借りて<table>の各要素に属する<foot>要素を選択します。


本の機能的等価物は次のようになります

<xsl:template match="table"> 
    <xsl:copy> 
     <text><xsl:apply-templates select="@*|node()"/></text> 
     <xsl:copy-of select="following-sibling::foot[ 
      generate-id(preceding-sibling::table[1]) = generate-id(current()) 
     ]" /> 
    </xsl:copy> 
</xsl:template> 

この変形例ではXSLキーが必要とされないであろう。結果は、両方のケースである:

<root> 
    <table> 
     <text>Table 1</text> 
     <foot>1.1</foot> 
     <foot>2.2</foot> 
    </table> 
    <p>...</p> 
    <p>...</p> 
    <table> 
     <text>Table X</text> 
     <foot>M.1</foot> 
     <foot>M.2</foot> 
    </table> 
    <p>...</p> 
    <p>...</p> 
    <table> 
     <text>Table 132</text> 
     <foot>A.A.E</foot> 
     <foot>234</foot> 
    </table> 
    <p>...</p> 
    <p>...</p> 
</root> 

注:

  • <xsl:element name="text">を使用しないでください。単に<text>と書くことができます。 <xsl:element>は、要素名が事前に決定されていない場合に使用します。
  • <xsl:for-each>を避けてください。 <xsl:template><xsl:apply-templates>を使用すると、ほとんどの状況で優れています。
+0

パーフェクト!ありがとう – Jagath

+0

XSLT 2.0環境では、@ michael.hor257kによって提示されたソリューションは、もちろんより良いです。 – Tomalak

1

これは基本的にグループ化の問題です。 XSLT 2.0を使用している場合、組み込みのグループ化機能を利用できます。

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

<xsl:template match="/root"> 
    <xsl:copy> 
     <xsl:for-each-group select="*" group-starting-with="table"> 
      <table> 
       <text> 
        <xsl:value-of select="."/> 
       </text> 
       <xsl:copy-of select="current-group()[self::foot]"/> 
      </table> 
      <xsl:copy-of select="current-group()[not(self::table or self::foot)]"/> 
     </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
関連する問題