Если вы хотите сделать это в 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>