xslt将父节点和子节点下的相同节点分组

时间:2015-03-13 06:35:54

标签: xslt

我想在Parent标记(<Item>)和子标记(<Sku>)中对具有相同名称的节点进行分组。

<Item>标记可能包含许多<Sku>子标记,但不应对其进行分组,而应将每个SkuItem中的元素分别进行分组。

我有一个输入xml文件,如下所示:

<Products>
  <Item>
    <Dimensions>
      <Height>10</Height>
    </Dimensions>
    <Dimensions>
      <Weight>10</Weight>
    </Dimensions>
    <Color>
      <Attribute>Orange</Attribute>
    </Color>
    <Color>
      <Attribute>Blue</Attribute> 
    </Color>
    <Sku>
     <Dimensions>
      <Height>10</Height>
     </Dimensions>
     <Dimensions>
      <Weight>10</Weight>
     </Dimensions>
     <Color>
      <Attribute>Orange</Attribute>
     </Color>
     <Color>
      <Attribute>Blue</Attribute> 
     </Color>
    </Sku>
    <Sku>
     <Dimensions>
      <Height>10</Height>
     </Dimensions>
     <Dimensions>
      <Weight>10</Weight>
     </Dimensions>
     <Color>
      <Attribute>Orange</Attribute>
     </Color>
     <Color>
      <Attribute>Blue</Attribute> 
     </Color>
    </Sku>
   </Item>
</Products>   

预期输出如下:

<Products>
  <Item>
        <Dimensions>
            <Height>10</Height>
            <Weight>10</Weight>
        </Dimensions>
        <Color>
            <Attribute>Orange</Attribute>
            <Attribute>Blue</Attribute>
        </Color>
        <Sku>
        <Dimensions>
            <Height>10</Height>
            <Weight>10</Weight>
        </Dimensions>
        <Color>
            <Attribute>Orange</Attribute>
            <Attribute>Blue</Attribute>
        </Color>
     </Sku>
     <Sku>
        <Dimensions>
            <Height>10</Height>
            <Weight>10</Weight>
        </Dimensions>
        <Color>
            <Attribute>Orange</Attribute>
            <Attribute>Blue</Attribute>
        </Color>
    </Sku>
  </Item>
</Products>

非常感谢任何帮助。 我使用了下面的xslt进行转换,但它只是在&#39;项目&#39;中出现的gouping元素。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="elements" match="Item/*[not(self::Sku)]" use="concat(name(), '|', generate-id(..))"/>

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

<xsl:template match="Item">
    <xsl:copy>
        <xsl:apply-templates select="@*" />
        <xsl:for-each select="*[generate-id() = generate-id(key('elements', concat(name(), '|', generate-id(..)))[1])]">
            <xsl:copy>
                <xsl:apply-templates select="key('elements', concat(name(), '|', generate-id(..)))/*"/>
            </xsl:copy>
        </xsl:for-each>
        <xsl:apply-templates select="Item" />
    </xsl:copy>
</xsl:template>
</xsl:stylesheet> 

1 个答案:

答案 0 :(得分:0)

您可以在两个分组之间共享相同的逻辑,如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:key name="elements" match="*" use="concat(name(), '|', generate-id(..))"/>

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

  <xsl:template name="GroupChildren">
    <xsl:param name="elements" select="*" />

    <xsl:for-each select="$elements[generate-id() = 
                                    generate-id(key('elements', 
                                                    concat(name(), '|', 
                                                           generate-id(..))
                                                   )[1])]">
      <xsl:copy>
        <xsl:apply-templates select="key('elements', 
                                         concat(name(), '|', generate-id(..)))/*"/>
      </xsl:copy>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="Item">
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <xsl:call-template name="GroupChildren">
        <xsl:with-param name="elements" select="*[not(self::Sku)]" />
      </xsl:call-template>
      <xsl:apply-templates select="Sku" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Sku">
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <xsl:call-template name="GroupChildren" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

在样本输入上运行时,结果为:

<Products>
  <Item>
    <Dimensions>
      <Height>10</Height>
      <Weight>10</Weight>
    </Dimensions>
    <Color>
      <Attribute>Orange</Attribute>
      <Attribute>Blue</Attribute>
    </Color>
    <Sku>
      <Dimensions>
        <Height>10</Height>
        <Weight>10</Weight>
      </Dimensions>
      <Color>
        <Attribute>Orange</Attribute>
        <Attribute>Blue</Attribute>
      </Color>
    </Sku>
    <Sku>
      <Dimensions>
        <Height>10</Height>
        <Weight>10</Weight>
      </Dimensions>
      <Color>
        <Attribute>Orange</Attribute>
        <Attribute>Blue</Attribute>
      </Color>
    </Sku>
  </Item>
</Products>