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>

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

提前感谢。。。

这可能会奏效,或者至少会给你一个开始:

<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 for不起作用,您也可以尝试使用param运行xsl:call-template

还要注意,xsl:copy不能很好地与太多的XSL引擎配合使用,因此您可能需要使用其他东西(例如,使用apply-templates并为元素编写模板(。

我最终使用了一个Muenchian分组,它对我来说效果很好。

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>

工作示例

相关内容

  • 没有找到相关文章

最新更新