Как улучшить мюнхенскую группировку XSLT?

Благодаря помощи Niraj и hr_117 Мне удалось получить шаблон XSL, который превращает этот XML...

<bookings>
  <entry>
    <event>Christmas</event>
    <attendees>2</attendees>
  </entry>
  <entry>
    <event>Halloween</event>
    <attendees>2</attendees>
  </entry>
  <entry>
    <event>Easter</event>
    <attendees>1</attendees>
  </entry>
  <entry>
    <event>Easter</event>
    <attendees>1</attendees>
  </entry>
</bookings>

... в этот вывод:

Рождество: 1 заказ(а)

Хэллоуин: 1 заказ(а)

Пасха: 2 бронирование(я)

Это мой XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="data">
  <xsl:apply-templates select="bookings"/>
</xsl:template>

<xsl:key name="bookings-within-period" match="bookings/entry" use="event" />

<xsl:template match="bookings">
  <xsl:for-each select="entry[count(. | key('bookings-within-period', event)[1]) = 1]">
      <p>
          <xsl:value-of select="concat(event,': ')" />
          <xsl:value-of select="count(key('bookings-within-period', event))" />
          <xsl:text> booking(s)</xsl:text>          
      </p>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Как я могу заставить эту функцию также вычислять сумму attendees?

Это вывод, который мне нужен:

Рождество: 1 заказ(а), 2 посетителя(ей)

Хэллоуин: 1 заказ(а), 2 посетителя(ей)

Пасха: 2 бронирования, 2 участника (ов)

Спасибо всем, кто может помочь!


person Tintin81    schedule 16.05.2013    source источник


Ответы (2)


Расширенный XSLT выглядит следующим образом:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="data">
    <xsl:apply-templates select="bookings"/>
  </xsl:template>

  <xsl:key name="bookings-within-period" match="bookings/entry" use="event" />

  <xsl:template match="bookings">
    <xsl:for-each select="entry[count(. | key('bookings-within-period', event)[1]) = 1]">
      <p>
        <xsl:value-of select="concat(event,': ')" />
        <xsl:value-of select="count(key('bookings-within-period', event))" />
        <xsl:text> booking(s), </xsl:text>
        <xsl:value-of select="sum(key('bookings-within-period', event)/attendees)" />
        <xsl:text> attendee(s)</xsl:text>
      </p>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

где у нас есть <xsl:value-of select="sum(key('bookings-within-period', event)/attendees)" /> для суммирования всех участников

person Navin Rawat    schedule 16.05.2013
comment
Отлично, большое спасибо! И последнее: давайте предположим, что у каждого узла <event> также есть узел <date>. Можно ли тогда отсортировать вывод по дате? - person Tintin81; 16.05.2013

Использование key('bookings-within-period', event) дает вам элемент entry в каждой группе, а затем sum(key('bookings-within-period', event)/attendees) дает вам сумму attendees в каждой группе.

И вам нужно сделать это внутри for-each, где первый элемент entry в каждой группе является узлом контекста, если это не ясно.

person Martin Honnen    schedule 16.05.2013
comment
Спасибо. Я думал, что пробовал это раньше, но оказалось, что я не мог видеть лес за всеми деревьями. Я просто бросил монету и Navin выиграл, поэтому я отметил его ответ как правильный ;-) - person Tintin81; 16.05.2013