Как отфильтровать XML с группой? - PullRequest
0 голосов
/ 06 февраля 2012

Это мой 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, как показано ниже

* * 1010
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. если вы берете общую цену, это должна быть сумма этой группы

Как мне это сделать в xsl файле

в надежде на вашу помощь

Ответы [ 2 ]

1 голос
/ 06 февраля 2012

Если вы хотите сделать это в XSLT1.0, вам нужно использовать технику, называемую Meunchian Grouping.

В вашем случае вы указали идентификатор отеля, тип питания, категорию, взрослого и ребенка, что означает довольно сложный ключ

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

Обратите внимание на использование символа 'pipe' для разделения различных полей в ключе. Важно, чтобы этот символ фактически не встречался ни в одном из полей.

Далее (для данного идентификатора отеля) вы начинаете с поиска первого элемента в каждой группе, например:

<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>
0 голосов
/ 06 февраля 2012

решение в 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...