XSLT:合并兄弟节点的子元素

时间:2013-04-15 19:35:08

标签: xml xslt xslt-1.0

我对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>

所以我认为我需要以某种方式按索引分组然后只选择每个元素,但我不太确定如何做到这一点。

提前致谢...

3 个答案:

答案 0 :(得分: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[@index=@index]/*">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:element>
</xsl:for-each>

但是XSL一般不适合参数化操作。如果interal不起作用,您也可以尝试xsl:call-template运行with param

另请注意,xsl:copy对于太多的XSL引擎并不适用,因此您可能需要使用其他内容(例如,使用apply-templates并为您的元素编写模板)。

答案 1 :(得分:0)

我最终使用的Muenchian Grouping对我来说效果很好。

答案 2 :(得分:0)

Muenchian分组的例子......

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