Группировка по 2 полям в XSL - PullRequest
6 голосов
/ 10 ноября 2009

У меня есть следующий xml:

<page>
   <document>
      <id>1001</id>
      <cur>USD</cur>
      <date>01.01.2009</date>
      <amount>10</amount>
   </document>
   <document>
      <id>1001</id>
      <cur>USD</cur>
      <date>02.01.2009</date>
      <amount>15</amount>
   </document>
   <document>
      <id>1001</id>
      <cur>JPY</cur>
      <date>01.01.2009</date>
      <amount>5</amount>
   </document>
   <document>
      <id>1002</id>
      <cur>USD</cur>
      <date>01.01.2009</date>
      <amount>5</amount>
   </document>
   ...
</page>

И мне нужно преобразовать его в HTML. Записи должны быть сгруппированы по id и cur . И после каждой группы общая сумма должна быть показана. Итак, мы хотим что-то вроде этого:

Bill: id=1001, cur=USD
      date=01.01.2009   amount=10
      date=02.01.2009   amount=15
      total amount=25
Bill: id=1001, cur=JPY
      date=01.01.2009   amount=5
      total amount=5
Bill: id=1002, cur=USD
      date=01.01.2009   amount=5
      total amount=5
...

Как мне добиться этого с помощью XSL?

Когда я попытался найти ответ в Google, я нашел метод Мюнхена, но он слишком сложен, когда мы хотим сгруппировать результат по 2 полям. Я новичок в xsl, и это немного сложно для меня. Я также нашел оператор xslt 2.0 для каждой группы. Поддерживается ли это основными браузерами? Это нормально, или мы должны полагаться только на xslt 1.0?

Ответы [ 2 ]

3 голосов
/ 10 ноября 2009

Вы можете сделать это с XSLT 1.0

Метод, который я здесь использую, заключается в создании составного ключа с двумя полями: id и cur. Позже я применяю шаблоны к первому документу в каждой группе. Затем внутри шаблона я перебираю отдельные документы и, наконец, суммирую поле количества документов.

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

<xsl:key name="idcur" match="document" use="concat(id,cur)"/>

<xsl:template match="/page">
    <xsl:apply-templates select="document[generate-id() = generate-id(key('idcur',concat(id,cur))[1])]"/>
</xsl:template>

<xsl:template match="document">
<xsl:variable name="document" select="key('idcur',concat(id,cur))"/>
Bill: id=<xsl:value-of select="id"/>, cur=<xsl:value-of select="cur"/>
    <xsl:for-each select="$document">
      date=<xsl:value-of select="date"/>   amount=<xsl:value-of select="amount"/>
    </xsl:for-each>
      total amount=<xsl:value-of select="sum($document/amount)"/>
</xsl:template>
</xsl:stylesheet>

Выход:

Bill: id=1001, cur=USD
      date=01.01.2009   amount=10
      date=02.01.2009   amount=15
      total amount=25
Bill: id=1001, cur=JPY
      date=01.01.2009   amount=5
      total amount=5
Bill: id=1002, cur=USD
      date=01.01.2009   amount=5
      total amount=5
0 голосов
/ 10 ноября 2009

Объединение двух полей для создания составного ключа небезопасно, если только вы не уверены, что все такие созданные ключи являются уникальными. Этот метод безопаснее, я думаю:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text"/>

<xsl:key name="ids" match="document" use="id"/>
<xsl:key name="currencies" match="document" use="cur"/>

<xsl:template match="/page">
    <xsl:apply-templates select="document[generate-id() = generate-id(key('ids',id)[1])]"/>
</xsl:template>

<xsl:template match="document">
  <xsl:for-each select="key('ids',id)[generate-id() = generate-id(key('currencies', cur)[id=current()/id][1])]">
    <xsl:variable name="bills" select="key('ids', id)[cur = current()/cur]"/>
    <xsl:text>Bill: id=</xsl:text>
    <xsl:value-of select="id"/>
    <xsl:text>, cur=</xsl:text>
    <xsl:value-of select="cur"/>
    <xsl:for-each select="$bills">
      <xsl:text>&#10;date=</xsl:text>
      <xsl:value-of select="date"/>
      <xsl:text>   amount=</xsl:text>
      <xsl:value-of select="amount"/>
    </xsl:for-each>
    <xsl:text>&#10;total amount=</xsl:text>
    <xsl:value-of select="sum($bills/amount)"/>
    <xsl:text>&#10;</xsl:text>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...