如何使用 xslt 1.0 按 xml 节点分组

how to group-by xml nodes using xslt 1.0

这是我的xml

<hotel>
    <rooms>
        <room>
            <rates>
                <rates id="1" adult="1" child="0"><rates>
                <rates id="2" adult="2" child="0"><rates>
                <rates id="3" adult="1" child="0"><rates>
            </rates>
        </room>
        <room>
            <rates>
                <rates id="4" adult="1" child="0"><rates>
                <rates id="5" adult="2" child="0"><rates>
                <rates id="6" adult="2" child="0"><rates>
            </rates>
        </room>
    </rooms>
</hotel>

如何使用 xslt 1.0

基于 "Adults" 和 "Child" 进行分组

同一个费率节点中的成人和儿童以及分组方式

我需要如下结果,

<hotel>
    <rooms>
        <room>
            <rates>
                <rates id="1" adult="1" child="0"><rates>
                <rates id="3" adult="1" child="0"><rates>
                <rates id="4" adult="1" child="0"><rates>
            </rates>
        </room>
        <room>
            <rates>
                <rates id="2" adult="2" child="0"><rates>
                <rates id="5" adult="2" child="0"><rates>
                <rates id="6" adult="2" child="0"><rates>
            </rates>
        </room>
    </rooms>
</hotel>

Example of Muenchian Grouping...

XML 输入(修改为格式正确并添加 child 值的示例)

<hotel>
    <rooms>
        <room>
            <rates>
                <rates id="1" adult="1" child="0"/>
                <rates id="1A" adult="2" child="3"/>
                <rates id="2" adult="2" child="0"/>
                <rates id="3" adult="1" child="0"/>
            </rates>
        </room>
        <room>
            <rates>
                <rates id="4" adult="1" child="0"/>
                <rates id="5" adult="2" child="0"/>
                <rates id="6" adult="2" child="0"/>
                <rates id="6A" adult="2" child="3"/>
            </rates>
        </room>
    </rooms>
</hotel>

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="*"/>

  <!--Group "rates" by combining the adult and child attribute values.-->
  <xsl:key name="rates" match="rates" use="concat(@adult,'|',@child)"/>

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

  <xsl:template match="rooms">
    <rooms>
      <!--
      This for-each will match the first "rates" element in each group.
      Nothing is done with the matched "rates" element; we only do this 
      to wrap the group with "room".
      -->
      <xsl:for-each select="room/rates/rates[count(.|key('rates',concat(@adult,'|',@child))[1])=1]">
        <room>
          <!--This apply-templates selects all "rates" in the group.-->
          <xsl:apply-templates select="key('rates',concat(@adult,'|',@child))"/>
        </room>
      </xsl:for-each>      
    </rooms>
  </xsl:template>

</xsl:stylesheet>

XML输出

<hotel>
   <rooms>
      <room>
         <rates id="1" adult="1" child="0"/>
         <rates id="3" adult="1" child="0"/>
         <rates id="4" adult="1" child="0"/>
      </room>
      <room>
         <rates id="1A" adult="2" child="3"/>
         <rates id="6A" adult="2" child="3"/>
      </room>
      <room>
         <rates id="2" adult="2" child="0"/>
         <rates id="5" adult="2" child="0"/>
         <rates id="6" adult="2" child="0"/>
      </room>
   </rooms>
</hotel>