XSLT: расчет результатов для отфильтрованного подмножества и полного набора данных за один раз - PullRequest
0 голосов
/ 16 марта 2011

Мой xslt-fu все еще очень слаб. Первые дни.

Мои данные XML представляют собой список компаний, их поставщиков услуг и их значение.

Мне удалось сгруппировать по поставщикам услуг, чтобы я мог видеть, какие поставщики услуг имеют наибольшую долю рынка по количеству клиентов и общей рыночной стоимости.

Это хорошо работает для всего рынка, но я также хотел бы вывести значения и для «100 лучших (по стоимости) компаний». Я понятия не имею, как добавить это.

Текущий XSLT (см. Комментарии, где я хотел бы добавить дополнительные данные):

<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
    <xsl:output method="html" indent="no"/>

    <xsl:key name="providerkey" match="/dsQueryResponse/Rows/Row" use="@svcprovider" />

    <xsl:template match="/">
        <table>
            <tr>
                <th>Service Provider</th>
                <th>Total Market value</th>
                <th>No. Cos</th>
                <th>Market value from top 100 cos</th>
                <th>No. cos from top 100</th>
            </tr>

            <xsl:for-each select="/dsQueryResponse/Rows/Row[generate-id(.)=generate-id(key('providerkey',@svcprovider)[1])]">
                <xsl:sort select="count(key('providerkey',@svcprovider))" order="descending" data-type="number" />
                <xsl:variable name="totalvalue" select="sum(/dsQueryResponse/Rows/Row[@svcprovider=current()/@svcprovider]/@covalue)" />
                <tr>
                    <td>
                        <xsl:value-of select="current()/@svcprovider"/>
                    </td> 
                    <td>
                        <xsl:value-of select="$totalvalue" />
                    </td> 
                    <td>
                        <xsl:value-of select="count(key('providerkey',@svcprovider))"/>
                    </td>
                    <td>
                        <!-- How do I get total value, but only from the top 100 companies ?? -->
                    </td>
                    <td>
                        <!-- How do I get total no. of companies, but only from the top 100 ?? -->
                    </td>                       

                </tr>
            </xsl:for-each>
        </table>
    </xsl:template>

</xsl:stylesheet>

Пример XML-данных:

<Rows>
    <Row coname="client name 1" svcprovider="svc provider name 1" covalue="998" />
    <Row coname="client name 2" svcprovider="svc provider name 2" covalue="1081" />
    <!-- ...etc... -->

</Rows>

Очевидно, что есть более 100 строк. В основном я использую это для расчета доли рынка по всему рынку, и хотел бы также рассчитать для топ-конца.

Полагаю, мне нужно добавить дополнительный цикл сортировки / фильтрации, но я не уверен, как его реализовать.

Заранее спасибо

John

1 Ответ

1 голос
/ 16 марта 2011

Попробуйте что-то вроде этого:

<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="html" indent="yes"/>
    <xsl:param name="pTopNumber" select="3"/>

    <xsl:key name="providerkey"
        match="/dsQueryResponse/Rows/Row" use="@svcprovider" />

    <xsl:variable name="vrtfTopCompanies">
     <xsl:for-each select="/*/*/Row">
       <xsl:sort select="covalue"
            data-type="number" order="descending"/>
       <xsl:if test="not(position() > $pTopNumber)">
        <xsl:copy-of select="."/>
       </xsl:if>
     </xsl:for-each>
    </xsl:variable>

    <xsl:variable name="vTopRows"
         select="msxsl:node-set($vrtfTopCompanies)/*"/>

    <xsl:template match="/">
        <table>
            <tr>
                <th>Service Provider</th>
                <th>Total Market value</th>
                <th>No. Cos</th>
                <th>Market value from top 100 cos</th>
                <th>No. cos from top 100</th>
            </tr>
            <xsl:for-each select=
              "/dsQueryResponse/Rows/Row
                       [generate-id()
                       =
                       generate-id(key('providerkey',@svcprovider)[1])
                       ]">
                <xsl:sort select="count(key('providerkey',@svcprovider))"
                          order="descending" data-type="number" />
                <xsl:variable name="totalvalue" select=
                   "sum(/dsQueryResponse/Rows
                                /Row[@svcprovider=current()/@svcprovider]/@covalue)" />
                <tr>
                    <td>
                        <xsl:value-of select="current()/@svcprovider"/>
                    </td>
                    <td>
                        <xsl:value-of select="$totalvalue" />
                    </td>
                    <td>
                        <xsl:value-of select="count(key('providerkey',@svcprovider))"/>
                    </td>
                    <td>
                        <!-- How do I get total value, but only from the top 100 companies ?? -->
                        <xsl:value-of select="sum($vTopRows[@svcprovider=current()/@svcprovider]/@covalue)"/>
                    </td>
                    <td>
                        <!-- How do I get total no. of companies, but only from the top 100 ?? -->
                        <xsl:value-of select="count(key('providerkey',@svcprovider)[@coname = $vTopRows/@coname])"/>
                    </td>
                </tr>
            </xsl:for-each>
        </table>
    </xsl:template>
</xsl:stylesheet>

при применении к следующему документу XML :

<dsQueryResponse>
    <Rows>
        <Row coname="client name 1" svcprovider="svc provider name 1" covalue="998" />
        <Row coname="client name 2" svcprovider="svc provider name 2" covalue="1081" />
        <Row coname="client name 3" svcprovider="svc provider name 3" covalue="998" />
        <Row coname="client name 4" svcprovider="svc provider name 4" covalue="2081" />
        <Row coname="client name 5" svcprovider="svc provider name 5" covalue="3998" />
        <Row coname="client name 2" svcprovider="svc provider name 2" covalue="1081" />
        <Row coname="client name 1" svcprovider="svc provider name 1" covalue="998" />
        <Row coname="client name 2" svcprovider="svc provider name 2" covalue="1081" />
        <Row coname="client name 1" svcprovider="svc provider name 1" covalue="998" />
        <Row coname="client name 2" svcprovider="svc provider name 2" covalue="1081" />
    </Rows>
</dsQueryResponse>

результат равен :

<table>
    <tr>
        <th>Service Provider</th>
        <th>Total Market value</th>
        <th>No. Cos</th>
        <th>Market value from top 100 cos</th>
        <th>No. cos from top 100</th>
    </tr>
    <tr>
        <td>svc provider name 2</td>
        <td>4324</td>
        <td>4</td>
        <td>1081</td>
        <td>4</td>
    </tr>
    <tr>
        <td>svc provider name 1</td>
        <td>2994</td>
        <td>3</td>
        <td>998</td>
        <td>3</td>
    </tr>
    <tr>
        <td>svc provider name 3</td>
        <td>998</td>
        <td>1</td>
        <td>998</td>
        <td>1</td>
    </tr>
    <tr>
        <td>svc provider name 4</td>
        <td>2081</td>
        <td>1</td>
        <td>0</td>
        <td>0</td>
    </tr>
    <tr>
        <td>svc provider name 5</td>
        <td>3998</td>
        <td>1</td>
        <td>0</td>
        <td>0</td>
    </tr>
</table>
...