如何使用group wise过滤xml?

时间:2012-02-06 08:21:45

标签: xslt

这是我的xml文件

<hotels>
    <item>
        <hotelId>1001</hotelId>
        <boardType>Room Only</boardType>
        <rooms>
            <item>
                <roomCategory>Standard Single Room</roomCategory>
                <paxes>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                </paxes>
                <totalRoomRate>10</totalRoomRate>
            </item>
            <item>
                <roomCategory>Standard Single Room</roomCategory>
                <paxes>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                    <item>
                        <paxType>Child</paxType>
                        <age>1</age>
                    </item>
                </paxes>
                <totalRoomRate>15</totalRoomRate>
            </item>
            <item>
                <roomCategory>Standard Single Room</roomCategory>
                <paxes>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                    <item>
                        <paxType>Child</paxType>
                        <age>14</age>
                    </item>
                </paxes>
                <totalRoomRate>20</totalRoomRate>
            </item>
            <item>
                <roomCategory>Standard Single Room</roomCategory>
                <paxes>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                </paxes>
                <totalRoomRate>20</totalRoomRate>
            </item>
            <item>
                <roomCategory>Standard Single Room</roomCategory>
                <paxes>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                    <item>
                        <paxType>Child</paxType>
                        <age>14</age>
                    </item>
                    <item>
                        <paxType>Child</paxType>
                        <age>10</age>
                    </item>
                </paxes>
                <totalRoomRate>25</totalRoomRate>
            </item>
            <item>
                <roomCategory>Standard Single Room</roomCategory>
                <paxes>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                    <item>
                        <paxType>Child</paxType>
                        <age>14</age>
                    </item>
                    <item>
                        <paxType>Child</paxType>
                        <age>10</age>
                    </item>
                </paxes>
                <totalRoomRate>20</totalRoomRate>
            </item>
            <item>
                <roomCategory>Standard Single Room</roomCategory>
                <paxes>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                </paxes>
                <totalRoomRate>20</totalRoomRate>
            </item>
        </rooms>
    </item>
    <item>
        <hotelId>1002</hotelId>
        <boardType>Room Only</boardType>
        <rooms>
            <item>
                <roomCategory>Double/twin Deluxe</roomCategory>
                <paxes>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                </paxes>
                <totalRoomRate>10</totalRoomRate>
            </item>
            <item>
                <roomCategory>Double/twin Deluxe</roomCategory>
                <paxes>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                </paxes>
                <totalRoomRate>12</totalRoomRate>
            </item>
        </rooms>
    </item>
    <item>
        <hotelId>1003</hotelId>
        <boardType>Bed And Breakfast</boardType>
        <rooms>
            <item>
                <roomCategory>Double/twin Deluxe</roomCategory>
                <paxes>
                    <item>
                        <paxType>Adult</paxType>
                        <age>30</age>
                    </item>
                    <item>
                        <paxType>Child</paxType>
                        <age>3</age>
                    </item>
                </paxes>
                <totalRoomRate>20</totalRoomRate>
            </item>
        </rooms>
    </item>
</hotels>

XML输出我在下面显示


Hotel ID: 1001

Room Type              Board Type    Quantity  Adults   Child    Price
Standard Single Room   Room Only     1           1          0      10
Standard Single Room   Room Only     1           1          1      15
Standard Single Room   Room Only     1           1          1      20
Standard Single Room   Room Only     1           2          0      20
Standard Single Room   Room Only     1           1          2      25
Standard Single Room   Room Only     1           1          2      20
Standard Single Room   Room Only     1           2          0      20


Hotel ID: 1002

Room Type              Board Type    Quantity   Adults  Child     Price
Double/twin Deluxe     Room Only     1           1        0        10
Double/twin Deluxe     Room Only     1           1        0        12

Hotel ID: 1003

Room Type              Board Type    Quantity   Adults  Child     Price
Double/twin Deluxe     Bed And Breakfast  1      1        1        20

但我需要用xsl过滤上面的结果,如下所示


Hotel ID: 1001

Room Type              Board Type     Quantity   Adults   Child    Price
Standard Single Room   Room Only         1         1        0       10
Standard Single Room   Room Only         2         1        1       35
Standard Single Room   Room Only         2         2        0       40
Standard Single Room   Room Only         2         1        2       45

Hotel ID: 1002

Room Type              Board Type     Quantity   Adults   Child    Price
Double/twin Deluxe     Room Only         2         1        0       22

Hotel ID: 1003

Room Type              Board Type     Quantity   Adults   Child    Price
Double/twin Deluxe     Bed And Breakfast 1         1        1       20

  1. 如果您采取总量,它应该是相同的“房间类型”,“董事会类型”,“成人”和“儿童”

  2. 如果您采用总价格,它应该是该组的总数

  3. 我是如何在xsl文件中执行此操作的

    希望得到你的帮助

2 个答案:

答案 0 :(得分:1)

如果要在XSLT1.0中执行此操作,则需要使用名为Meunchian Grouping的技术。

在您的情况下,您正在通过酒店ID,董事会类型,类别,成人和儿童进行搜索,这意味着定义了相当复杂的密钥

<xsl:key 
   name="items" 
   match="rooms/item" 
   use="concat(../../hotelId, 
      '|', ../../boardType, 
      '|', roomCategory, 
      '|', count(paxes/item[paxType='Adult']), 
      '|', count(paxes/item[paxType='Child']))" />

请注意使用'pipe'字符来分隔键中的各个字段。重要的是,这个角色实际上不会出现在任何领域本身。

接下来(对于给定的酒店ID),您首先找到每个组中的第一个元素,如下所示:

<xsl:apply-templates 
   select="rooms/item[generate-id() 
      = generate-id(key('items', 
         concat(../../hotelId, 
         '|', ../../boardType, 
         '|', roomCategory, 
         '|', count(paxes/item[paxType='Adult']), 
         '|', count(paxes/item[paxType='Child'])))[1])]" 
  mode="group"/>

然后,一旦匹配了组中的第一个元素,就可以循环遍历组中的所有元素,或者在您的情况下,将它们聚合在一起

因此,给出以下XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html" indent="yes"/>
   <xsl:key name="items" match="rooms/item" use="concat(../../hotelId, '|', ../../boardType, '|', roomCategory, '|', count(paxes/item[paxType='Adult']), '|', count(paxes/item[paxType='Child']))"/>

   <xsl:template match="/hotels">
      <xsl:apply-templates select="item"/>
   </xsl:template>

   <xsl:template match="hotels/item">
      <h1>
         <xsl:value-of select="concat('Hotel ID: ', hotelId)"/>
      </h1>
      <table>
         <thead>
            <tr>
               <th>Room Type</th>
               <th>Board Type</th>
               <th>Quantity</th>
               <th>Adults</th>
               <th>Child</th>
               <th>Price</th>
            </tr>
         </thead>
         <tbody>
            <xsl:apply-templates select="rooms/item[generate-id() = generate-id(key('items', concat(../../hotelId, '|', ../../boardType, '|', roomCategory, '|', count(paxes/item[paxType='Adult']), '|', count(paxes/item[paxType='Child'])))[1])]" mode="group"/>
         </tbody>
      </table>
   </xsl:template>

   <xsl:template match="rooms/item" mode="group">
      <xsl:variable name="groupitems" select="key('items', concat(../../hotelId, '|', ../../boardType, '|', roomCategory, '|', count(paxes/item[paxType='Adult']), '|', count(paxes/item[paxType='Child'])))"/>
      <tr>
         <td>
            <xsl:value-of select="roomCategory"/>
         </td>
         <td>
            <xsl:value-of select="../../boardType"/>
         </td>
         <td>
            <xsl:value-of select="count($groupitems)"/>
         </td>
         <td>
            <xsl:value-of select="count(paxes/item[paxType='Adult'])"/>
         </td>
         <td>
            <xsl:value-of select="count(paxes/item[paxType='Child'])"/>
         </td>
         <td>
            <xsl:value-of select="sum($groupitems/totalRoomRate)"/>
         </td>
      </tr>
   </xsl:template>
</xsl:stylesheet>

当应用于您的示例XML时,输出以下内容:

<h1>Hotel ID: 1001</h1>
<table>
   <thead>
      <tr>
         <th>Room Type</th>
         <th>Board Type</th>
         <th>Quantity</th>
         <th>Adults</th>
         <th>Child</th>
         <th>Price</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>Standard Single Room</td>
         <td>Room Only</td>
         <td>1</td>
         <td>1</td>
         <td>0</td>
         <td>10</td>
      </tr>
      <tr>
         <td>Standard Single Room</td>
         <td>Room Only</td>
         <td>2</td>
         <td>1</td>
         <td>1</td>
         <td>35</td>
      </tr>
      <tr>
         <td>Standard Single Room</td>
         <td>Room Only</td>
         <td>2</td>
         <td>2</td>
         <td>0</td>
         <td>40</td>
      </tr>
      <tr>
         <td>Standard Single Room</td>
         <td>Room Only</td>
         <td>2</td>
         <td>1</td>
         <td>2</td>
         <td>45</td>
      </tr>
   </tbody>
</table>
<h1>Hotel ID: 1002</h1>
<table>
   <thead>
      <tr>
         <th>Room Type</th>
         <th>Board Type</th>
         <th>Quantity</th>
         <th>Adults</th>
         <th>Child</th>
         <th>Price</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>Double/twin Deluxe</td>
         <td>Room Only</td>
         <td>2</td>
         <td>1</td>
         <td>0</td>
         <td>22</td>
      </tr>
   </tbody>
</table>
<h1>Hotel ID: 1003</h1>
<table>
   <thead>
      <tr>
         <th>Room Type</th>
         <th>Board Type</th>
         <th>Quantity</th>
         <th>Adults</th>
         <th>Child</th>
         <th>Price</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>Double/twin Deluxe</td>
         <td>Bed And Breakfast</td>
         <td>1</td>
         <td>1</td>
         <td>1</td>
         <td>20</td>
      </tr>
   </tbody>
</table>

答案 1 :(得分:0)

XSLT 2.0中的解决方案:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
    <xsl:for-each select="hotels/item">
        <h1>Hotel ID: <xsl:value-of select="hotelId"/></h1>
        <br/>
        <table>
            <tbody>
                <tr>
                    <th>Room Type</th>
                    <th>Board Type</th>
                    <th>Quantity</th>
                    <th>Adults</th>
                    <th>Child</th>
                    <th>Price</th>
                </tr>
                <xsl:variable name="BT" select="boardType"/>
                <xsl:for-each-group select="rooms/item" group-by="count(paxes/item[paxType='Adult']) * 1000 + count(paxes/item[paxType='Child'])">
                    <xsl:for-each select=".">
                        <tr>
                            <td><xsl:value-of select="roomCategory"/></td>
                            <td><xsl:value-of select="$BT"/></td>
                            <td><xsl:value-of select="count(current-group())"/></td>
                            <td><xsl:value-of select="count(./paxes/item[paxType='Adult'])"/></td>
                            <td><xsl:value-of select="count(./paxes/item[paxType='Child'])"/></td>
                            <td><xsl:value-of select="sum(current-group()/totalRoomRate)"/></td>
                        </tr>
                    </xsl:for-each>
                </xsl:for-each-group>
            </tbody>
        </table>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

结果为

<h1>Hotel ID: 1001</h1><br><table>
    <tbody>
        <tr>
            <th>Room Type</th>
            <th>Board Type</th>
            <th>Quantity</th>
            <th>Adults</th>
            <th>Child</th>
            <th>Price</th>
        </tr>
        <tr>
            <td>Standard Single Room</td>
            <td>Room Only</td>
            <td>1</td>
            <td>1</td>
            <td>0</td>
            <td>10</td>
        </tr>
        <tr>
            <td>Standard Single Room</td>
            <td>Room Only</td>
            <td>2</td>
            <td>1</td>
            <td>1</td>
            <td>35</td>
        </tr>
        <tr>
            <td>Standard Single Room</td>
            <td>Room Only</td>
            <td>2</td>
            <td>2</td>
            <td>0</td>
            <td>40</td>
        </tr>
        <tr>
            <td>Standard Single Room</td>
            <td>Room Only</td>
            <td>2</td>
            <td>1</td>
            <td>2</td>
            <td>45</td>
        </tr>
    </tbody>
</table>
<h1>Hotel ID: 1002</h1><br><table>
    <tbody>
        <tr>
            <th>Room Type</th>
            <th>Board Type</th>
            <th>Quantity</th>
            <th>Adults</th>
            <th>Child</th>
            <th>Price</th>
        </tr>
        <tr>
            <td>Double/twin Deluxe</td>
            <td>Room Only</td>
            <td>2</td>
            <td>1</td>
            <td>0</td>
            <td>22</td>
        </tr>
    </tbody>
</table>
<h1>Hotel ID: 1003</h1><br><table>
    <tbody>
        <tr>
            <th>Room Type</th>
            <th>Board Type</th>
            <th>Quantity</th>
            <th>Adults</th>
            <th>Child</th>
            <th>Price</th>
        </tr>
        <tr>
            <td>Double/twin Deluxe</td>
            <td>Bed And Breakfast</td>
            <td>1</td>
            <td>1</td>
            <td>1</td>
            <td>20</td>
        </tr>
    </tbody>
</table>