2013-04-15 64 views
1

我對XSLT有點新,但我試圖將兄弟節點的子元素合併到包含所有數據的單個節點中。XSLT:合併兄弟節點的子元素

因此,例如,我的數據結構看起來是這樣的:

<root> 
    <item> 
     <child index="0"> 
      <data>fooA</data> 
      <data>fooB</data> 
      <data>fooC</data> 
      <data>fooD</data> 
     </child> 
     <child index="1"> 
      <data>foo1</data> 
      <data>foo2</data> 
      <data>foo3</data> 
      <data>foo4</data> 
     </child> 
    </item> 
    <item> 
     <child index="0"> 
      <data>barE</data> 
      <data>barF</data> 
      <data>barG</data> 
      <data>barH</data> 
     </child> 
     <child index="1"> 
      <data>bar5</data> 
      <data>bar6</data> 
      <data>bar7</data> 
      <data>bar8</data> 
     </child> 
    </item> 
</root> 

,我想改變這樣的:

<root> 
    <item> 
     <child index="0"> 
      <data>fooA</data> 
      <data>fooB</data> 
      <data>fooC</data> 
      <data>fooD</data> 
      <data>barE</data> 
      <data>barF</data> 
      <data>barG</data> 
      <data>barH</data> 
     </child> 
     <child index="1"> 
      <data>foo1</data> 
      <data>foo2</data> 
      <data>foo3</data> 
      <data>foo4</data> 
      <data>bar5</data> 
      <data>bar6</data> 
      <data>bar7</data> 
      <data>bar8</data> 
     </child> 
    </item> 
</root> 

所以我想我需要以某種方式按指數然後只選擇每個元素,但我不太確定如何做到這一點。

在此先感謝...

+0

將是很難做到普遍。你想通過索引屬性進行分組,還是通過兩個元素的第n個子元素進行分組? – Nux

+0

索引屬性。 – rybl

回答

2

這可能會實現,或者至少給你一個開始:

<xsl:for-each select="//item[1]/child"> 
    <xsl:element name="child"> 
     <xsl:attribute name="index"><xsl:value-of select="@index" /></xsl:attribute> 
     <xsl:for-each select="//item/child[@[email protected]]/*"> 
      <xsl:copy-of select="."/> 
     </xsl:for-each> 
    </xsl:element> 
</xsl:for-each> 

但XSL一般不是最適合的參數化操作。如果interal for不起作用,你也可以試試xsl:call-template run with param

另請注意,xsl:copy不適用於太多的XSL引擎,因此您可能需要使用其他方法(例如,使用apply-templates併爲您的元素編寫模板)。

0

我結束了使用Muenchian Grouping這對我來說效果很好。 Muenchian分組的的

+1

儘管這在理論上可以回答這個問題,但[這將是更可取的](// meta.stackoverflow.com/q/8259)在這裏包括答案的基本部分,並提供了供參考的鏈接。 –

0

實施例...

XML輸入

<root> 
    <item> 
     <child index="0"> 
      <data>fooA</data> 
      <data>fooB</data> 
      <data>fooC</data> 
      <data>fooD</data> 
     </child> 
     <child index="1"> 
      <data>foo1</data> 
      <data>foo2</data> 
      <data>foo3</data> 
      <data>foo4</data> 
     </child> 
    </item> 
    <item> 
     <child index="0"> 
      <data>barE</data> 
      <data>barF</data> 
      <data>barG</data> 
      <data>barH</data> 
     </child> 
     <child index="1"> 
      <data>bar5</data> 
      <data>bar6</data> 
      <data>bar7</data> 
      <data>bar8</data> 
     </child> 
    </item> 
</root> 

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="childByIndex" match="child" use="@index"/> 

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

    <xsl:template match="/root"> 
    <root> 
     <item> 
     <xsl:for-each select="item/child[count(.|key('childByIndex',@index)[1])=1]"> 
      <child> 
      <xsl:apply-templates select="@*|key('childByIndex',@index)/*"/> 
      </child> 
     </xsl:for-each> 
     </item> 
    </root> 
    </xsl:template> 

</xsl:stylesheet> 

XML輸出

<root> 
    <item> 
     <child index="0"> 
     <data>fooA</data> 
     <data>fooB</data> 
     <data>fooC</data> 
     <data>fooD</data> 
     <data>barE</data> 
     <data>barF</data> 
     <data>barG</data> 
     <data>barH</data> 
     </child> 
     <child index="1"> 
     <data>foo1</data> 
     <data>foo2</data> 
     <data>foo3</data> 
     <data>foo4</data> 
     <data>bar5</data> 
     <data>bar6</data> 
     <data>bar7</data> 
     <data>bar8</data> 
     </child> 
    </item> 
</root> 

Working Example