Xsl: Как я могу группировать и сортировать по сумме? - PullRequest
2 голосов
/ 17 апреля 2009

у меня ниже xml

 <ResultCollection>
  <Result Id="551550" Pass="23" Fail="0" Owner="Dong"/>
  <Result Id="551565" Pass="4" Fail="3" Owner="Dong"/>
  <Result Id="551567" Pass="61" Fail="0" Owner="Mei"/>
  <Result Id="551580" Pass="10" Fail="1" Owner="Dong"/>  
  <Result Id="551580" Pass="0" Fail="4" Owner="Sen"/>  
  <Result Id="551548" Pass="1" Fail="12" Owner="Sen"/>
</ResultCollection>

И у меня есть xsl, который генерирует приведенную ниже сводку

Owner   Total   Pass    Fail
Dong    41  37  4
Mei     61  61  0
Sen     17  1   16

Как я могу отсортировать этот результат на основе Pass или Fail?

Мой xsl выглядит так

    <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>
  <xsl:key name="FeatureOwner" match="Result" use="@Owner" />
    <xsl:template match="/">
      <html>
        <head>
          <title>Result Summary</title>
        </head>
        <body>
                <table>
                  <tr>
                    <td>
                      <b>Owner</b></td>
                    <td>
                      <b>Total</b>
                    </td>
                    <td>
                      <b>Pass</b>
                    </td>
                    <td>
                      <b>Fail</b>
                    </td>
                  </tr>
                  <xsl:for-each select="ResultCollection/Result[generate-id(.) = generate-id(key('FeatureOwner', @Owner)[1])]">
                    <xsl:variable name="varFeatureOwner">
                      <xsl:value-of select="@Owner" />
                    </xsl:variable>
                    <xsl:variable name="totFailures" select="sum(//ResultCollection/Result[@Owner=$varFeatureOwner]/@Fail)" />
                    <xsl:variable name="totPass" select="sum(//ResultCollection/Result[@Owner=$varFeatureOwner]/@Pass)" />
                    <xsl:variable name="total" select="$totPass+$totFailures" />
                     <tr>
                        <td>
                          <xsl:value-of select="$varFeatureOwner"/>
                        </td>
                        <td>
                          <xsl:value-of select="$total"/>
                        </td>
                        <td>
                          <xsl:value-of select="$totPass"/>
                        </td>
                        <td>
                          <xsl:value-of select="$totFailures"/>
                        </td>
                      </tr>
                  </xsl:for-each>
                </table>
          </body>
      </html>
    </xsl:template>
</xsl:stylesheet>

1 Ответ

2 голосов
/ 17 апреля 2009

Примерно так ( Я перестроил ваш код, так как его очень не хватало ):

Это XSLT-преобразование :

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

 <xsl:param name="pSortBy" select="'Pass'"/>

 <xsl:key name="kResultByOwner" match="Result"
  use="@Owner"/>

    <xsl:template match="/">
        <table>
            <xsl:for-each select=
            "ResultCollection/Result
                 [generate-id(.) 
                 = 
                  generate-id(key('kResultByOwner', @Owner)[1])
                  ]">
                 <xsl:sort data-type="number" select=
                "sum(key('kResultByOwner', @Owner)
                               /@*[name()=$pSortBy])"/> 

                <xsl:variable name="totFailures" select=
                "sum(/ResultCollection/Result
                          [@Owner=current()/@Owner]
                              /@Fail
               )" />
                <xsl:variable name="totPass" select=
                "sum(/ResultCollection/Result
                           [@Owner=current()/@Owner]
                              /@Pass
               )" />

                <xsl:variable name="total" select=
                   "$totPass+$totFailures" />
                <tr>
                    <td>
                        <xsl:value-of select="current()/@Owner"/>
                    </td>
                    <td>
                        <xsl:value-of select="$total"/>
                    </td>
                    <td>
                        <xsl:value-of select="$totPass"/>
                    </td>
                    <td>
                        <xsl:value-of select="$totFailures"/>
                    </td>
                </tr>
            </xsl:for-each>
        </table>
    </xsl:template>
</xsl:stylesheet>

при применении к первоначально предоставленному документу XML :

<ResultCollection>
    <Result Id="551550" Pass="23" Fail="0" Owner="Dong"/>
    <Result Id="551565" Pass="4" Fail="3" Owner="Dong"/>
    <Result Id="551567" Pass="61" Fail="0" Owner="Mei"/>
    <Result Id="551580" Pass="10" Fail="1" Owner="Dong"/>
    <Result Id="551580" Pass="0" Fail="4" Owner="Sen"/>
    <Result Id="551548" Pass="1" Fail="12" Owner="Sen"/>
</ResultCollection>

дает желаемый результат ):

Sen        17    1  16
Dong       41   37   4
Mei        61   61   0

Обратите внимание на следующее :

  1. Суммирование значений атрибута @Pass или @Fail для элементов, принадлежащих только к текущей группе (использование функции key()).

  2. Использование инструкции <xsl:sort .../> для сортировки по необходимым суммам.

  3. Использование глобального параметра с именем pSortBy, который содержит имя атрибута по суммам для сортировки.

  4. Использование функции XSLT current()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...