在xml/xslt中对相同节点的子组进行分组/合并

Mat*_*t90 4 xml xslt merge nodes

我是XSLT的新手,手动更改它需要花费很多时间.

<GroupData ID="xxx" Key="4" Temp="yyy">
 <ItemData ID="zzz" Value="3"/>
</GroupData>

<GroupData ID="xxx" Key="4" Temp="yyy">
 <ItemData ID="www" Value="1982"/>
</GroupData>
Run Code Online (Sandbox Code Playgroud)

我希望将这些多个GroupData节点的子节点放在同一个组中,即

<GroupData ID="xxx" Key="4" Temp="yyy">
 <ItemData ID="zzz" Value="3"/>
 <ItemData ID="www" Value="1982"/>
</GroupData>
Run Code Online (Sandbox Code Playgroud)

所以我需要在GroupData的ID和Key属性上合并/组合/匹配它们(这些属性在文件中有所不同).还有一些没有Key属性.我怎样才能做到这一点?我读了一些其他的线程(例如,在C#中,但我没有这个可供我使用),我检查了W3学校,但这些都是非常基本的例子.我正在使用最新的XML Tools 2.3.2 r908 unicode(beta4)for Notepad ++来应用可能的转换(不知道它是否支持XSLT2.0或XSLT1.0).

编辑:尝试下面的建议和我遇到的各种事情,因为它有多个级别,可能没有唯一的ID:...

Ian*_*rts 6

如果它是XSLT 2.0,那么你可以使用嵌套 <xsl:for-each-group>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <Groups>
      <xsl:for-each-group select="/Groups/GroupData" group-by="@ID">
        <xsl:for-each-group select="current-group()" group-by="if(@Key) then @Key else 'no key'">
          <GroupData>
            <!-- Copy attributes off the *first* GroupData element in the group -->
            <xsl:copy-of select="current-group()[1]/@*"/>
            <!-- Copy ItemData children from *all* GroupData elements in the group -->
            <xsl:copy-of select="current-group()/ItemData" />
          </GroupData>
        </xsl:for-each-group>
      </xsl:for-each-group>
    </Groups>
  </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

(我假设您的输入文件具有根元素<Groups>并且不使用命名空间).

如果它是XSLT 1.0,那么你需要使用Muenchian分组:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="group-data" match="GroupData" use="concat(@ID, '___', @Key)" />
  <xsl:template match="/">
    <Groups>
      <!--
      Iterate over a node set containing just one GroupData element for
      each combination of ID and Key
      -->
      <xsl:for-each select="/Groups/GroupData[count( . | key('group-data', concat(@ID, '___', @Key))[1]) = 1]">
        <GroupData>
          <!-- Copy attributes from the "prototype" GroupData -->
          <xsl:copy-of select="@*"/>
          <!--
          Copy ItemData children from *all* GroupData elements with matching
          ID/Key
          -->
          <xsl:copy-of select="key('group-data', concat(@ID, '___', @Key))/ItemData" />
        </GroupData>
      </xsl:for-each>
    </Groups>
  </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

在这里,我通过创建合成key值,基于ID和Key属性进行单个分组传递{ID}___{Key}.