【问题标题】:XSL combining values of siblings if values of an attribute is same如果属性的值相同,则 XSL 组合兄弟的值
【发布时间】:2013-04-15 16:18:16
【问题描述】:

这就是我的 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

【问题讨论】:

    标签: xslt xslt-1.0 concat


    【解决方案1】:

    应该这样做:

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

    【讨论】:

      【解决方案2】:

      这是基于我对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>
      

      【讨论】:

      • 嗨,如果您还想合并NodeD 中的值怎么办?我有同样的要求,不同的是除了组合NodeE之外,我还想组合NodeD中的值具有相同的属性。你能评论一下这个post吗?谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-02
      • 2019-05-21
      • 2021-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多