Суммы и группировка по категориям с помощью XSLT - PullRequest
0 голосов
/ 19 февраля 2010

С XSLT, как я могу изменить следующее:

<root>
  <element id="1" State="Texas" County="Dallas" Population="2412827" />
  <element id="2" State="Texas" County="Harris" Population="3984349" />
  <element id="3" state="Georgia" County="Fulton" Population="1014932" />
  <element id="4" state="Georgia" County="Richmond" Population="212775" />
</root>

в

<body>
  <h2>Texas</h2>
  <table>
    <tr><td>Dallas</td><td>2412827</td></tr>
    <tr><td>Harris</td><td>3984349</td></tr>
    <tr><td>Total</td><td>6397176</td></tr>
  <h2>Georgia</h2>
  <table>
    <tr><td>Fulton</td><td>1014932</td></tr>
    <tr><td>Richmond</td><td>212775</td></tr>
    <tr><td>Total</td><td>1227707</td></tr>
  </table>
</body>

без явного кодирования названия каждого штата, потому что я бы облажался, если Пуэрто-Рико когда-либо станет государством.

1 Ответ

4 голосов
/ 19 февраля 2010

XSLT 1.0
Определите ключевое «состояние», из которого мы можем легко выбрать все состояния по названию состояния. Чем применить мюнхенскую группировку, чтобы найти уникальные состояния на входе.

Тогда все становится просто. Шаблон «элемент» будет применен один раз для каждого имени состояния и использует ключ () для извлечения всех записей для этого состояния.

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

    <xsl:output method="xml" indent="yes" />

    <xsl:key name="state" match="element" use="@State" />

    <xsl:template match="root">
        <body>
            <xsl:apply-templates select="element[generate-id(.)=generate-id(key('state',@State)[1])]"/>
        </body>
    </xsl:template>

    <xsl:template match="element">
        <h2><xsl:value-of select="@State" /></h2>
        <table>
            <xsl:for-each select="key('state',@State)">
                <tr>
                    <td>
                        <xsl:value-of select="@County" />
                    </td>
                    <td>
                        <xsl:value-of select="@Population" />
                    </td>
                </tr>
            </xsl:for-each>

            <tr>
                <td>
                    <xsl:text>Total</xsl:text>
                </td>
                <td>
                    <xsl:value-of select="sum(key('state',@State)/@Population)"/>
                </td>
            </tr>

        </table>
    </xsl:template>

</xsl:stylesheet>

XSLT 2.0

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

    <xsl:output method="xml" indent="yes" />

    <xsl:template match="root">
        <body>
            <xsl:for-each-group select="element" group-by="@State">
                <h2><xsl:value-of select="@State" /></h2>
                <table>
                    <xsl:for-each select="current-group()">
                        <tr>
                            <td>
                                <xsl:value-of select="@County" />
                            </td>
                            <td>
                                <xsl:value-of select="@Population" />
                            </td>
                        </tr>
                    </xsl:for-each>
                    <tr>
                        <td>
                            <xsl:text>Total</xsl:text>
                        </td>
                        <td>
                            <xsl:value-of select="format-number(sum(current-group()/@Population), '#########')"/>
                        </td>
                    </tr>
                </table>
            </xsl:for-each-group>
        </body>
    </xsl:template>

</xsl:stylesheet>
...