如果属性的值相同,则XSL组合兄弟姐妹的值

时间:2013-04-15 16:18:17

标签: xslt xslt-1.0 concat

这就是我的XML的样子

<?xml version="1.0"?>
<Nodes>
<NodeA NodeAattr="123">

<NodeB NodeBattr="456"></NodeB>

  <NodeC>
     <NodeD NodeDAttr="ValueD">
        <NodeE Name="ValueABC"> "555" </NodeE >
        <NodeE Name="ValueABC"> "666" </NodeE>
     </NodeD>
  </NodeC>
</NodeA>
</Nodes>

如果NodeE的Name属性值相同,则连接NodeE的值。 我的最终输出xml必须看起来像

<NodeA NodeAattr="123">

<NodeB NodeBattr="456"></NodeB>

  <NodeC>
     <NodeD="ValueD">
        <NodeE Name="ValueABC"> "555" , "666" </NodeE >
     </NodeD>
  </NodeC>
</NodeA>

请向我提供xsl ..我正在使用XSLT1.0

2 个答案:

答案 0 :(得分:2)

这应该这样做:

<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:strip-space elements="*" />

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

  <xsl:template match="NodeE">
    <xsl:copy>
      <xsl:apply-templates select="@* | text()" />
      <xsl:call-template name="NextSibling" />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="NodeE[@Name = preceding-sibling::*[1][self::NodeE]/@Name]" />

  <xsl:template match="NodeE" mode="includeSib">
    <xsl:value-of select="concat(',', .)"/>
    <xsl:call-template name="NextSibling" />
  </xsl:template>

  <xsl:template name="NextSibling">
    <xsl:apply-templates
      select="following-sibling::*[1]
                                  [self::NodeE and @Name = current()/@Name]"
      mode="includeSib" />
  </xsl:template>

</xsl:stylesheet>

在此输入上运行时(带有一些其他值来演示其功能):

<Nodes>
  <NodeA NodeAattr="123">

    <NodeB NodeBattr="456"></NodeB>

    <NodeC>
      <NodeD NodeDAttr="ValueD">
        <NodeE Name="ValueABC"> "555" </NodeE >
        <NodeE Name="ValueABC"> "666" </NodeE>
        <NodeE Name="ValueDEF"> "555" </NodeE >
        <NodeE Name="ValueDEF"> "565" </NodeE >
        <NodeE Name="ValueDEF"> "575" </NodeE >
        <NodeE Name="ValueABC"> "595" </NodeE >
      </NodeD>
    </NodeC>
  </NodeA>
</Nodes>

结果是:

<Nodes>
  <NodeA NodeAattr="123">
    <NodeB NodeBattr="456" />
    <NodeC>
      <NodeD NodeDAttr="ValueD">
        <NodeE Name="ValueABC"> "555" , "666" </NodeE>
        <NodeE Name="ValueDEF"> "555" , "565" , "575" </NodeE>
        <NodeE Name="ValueABC"> "595" </NodeE>
      </NodeD>
    </NodeC>
  </NodeA>
</Nodes>

答案 1 :(得分:1)

以下是基于我对question #825783的回答的解决方案:

样式表

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

  <xsl:key name="kNode" match="NodeE" use="@Name"/>

  <!--
  Identity transform: copy elements and attributes from input file as is
  -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>

  <!--
  Use Muenchian grouping to apply unique NodeE elements.
  See http://www.jenitennison.com/xslt/grouping/muenchian.html
  -->
  <xsl:template match="NodeE[generate-id() = 
                       generate-id(key('kNode', @Name)[1])]">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <!--
      Apply <NodeE> elements with the same @Name attribute value as the current
      element with the "concat" mode enabled
      -->
      <xsl:apply-templates select="key('kNode', @Name)" mode="concat"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="NodeE" mode="concat">
    <xsl:value-of select="."/>
    <!-- Add comma except if this is the last node -->
    <xsl:if test="position() != last()">
      <xsl:text>, </xsl:text>
    </xsl:if>
  </xsl:template>

  <!-- Drop other <NodeE> elements -->
  <xsl:template match="NodeE"/>

</xsl:stylesheet>

输入

使用JLRishe提供的输入:

<Nodes>
  <NodeA NodeAattr="123">

    <NodeB NodeBattr="456"></NodeB>

    <NodeC>
      <NodeD NodeDAttr="ValueD">
        <NodeE Name="ValueABC"> "555" </NodeE>
        <NodeE Name="ValueABC"> "666" </NodeE>
        <NodeE Name="ValueDEF"> "555" </NodeE>
        <NodeE Name="ValueDEF"> "565" </NodeE>
        <NodeE Name="ValueDEF"> "575" </NodeE>
        <NodeE Name="ValueABC"> "595" </NodeE>
      </NodeD>
    </NodeC>
  </NodeA>
</Nodes>

输出

这与JLRishe的输出不同,因为我对要求的理解不同:

<?xml version="1.0" encoding="utf-8"?>
<Nodes>
  <NodeA NodeAattr="123">
    <NodeB NodeBattr="456"/>
    <NodeC>
      <NodeD NodeDAttr="ValueD">
        <NodeE Name="ValueABC"> "555" ,  "666" ,  "595" </NodeE>
        <NodeE Name="ValueDEF"> "555" ,  "565" ,  "575" </NodeE>
      </NodeD>
    </NodeC>
  </NodeA>
</Nodes>