xsl:排序不按预期工作

时间:2018-01-10 18:04:45

标签: xml xslt xpath

这是我的xslt:

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

    <xsl:output doctype-public="-//W3C//DTD XHTML 1.1//EN"
                doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" />

    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt">
            <head>
                <title>teste</title>
            </head>
            <body>
                <xsl:apply-templates select="//produtos"/>


            </body>
        </html>
    </xsl:template>


    <xsl:template match="produto">

        <xsl:variable name="id" select="@id"/>

        <xsl:variable name="nr" select="count(//avaliacao[@produto = $id])"/>

        <xsl:variable name="stars" select="sum(//avaliacao[@produto = $id]/@stars)"/>

        <xsl:variable name="media" select="$stars div $nr"/>

        <xsl:if test="$media &gt; 2">

            <xsl:for-each select="//produto[@id = $id]">
                <xsl:sort select="string($media)" data-type="number" order="ascending"/>

                <xsl:value-of select="$media"/>

            </xsl:for-each>
        </xsl:if>


        </xsl:template>



        </xsl:stylesheet>

这是我的XML(它有点大):

        <produtos>

        <produto id="P01">
            <nome>Powerbank</nome>
            <descricao>Nova.</descricao>
            <caracteristicas nome="Powerbank" valor="19,99"/>
            <preco>19.99</preco>
            <data_ins>2017/10/16</data_ins>
            <transportadora empresa="CTT"/>
            <transportadora empresa="SEUR"/>
            <links_f href="https://ae01.alicdn.com/kf/HTB1YGZkLXXXXXb8XFXXq6xXFXXXr/Original-DOCA-font-b-Power-b-font-font-b-Ban-b-font-Real-5000Mah-Li-polymer.jpg"/>              
            <vendedor id="U07"/>
        </produto>

                <avaliacoes>

            <avaliacao produto="P04" autor="U02" stars="5"/>
            <avaliacao produto="P03" autor="U02" stars="4"/>
            <avaliacao produto="P01" autor="U01" stars="5"/>
            <avaliacao produto="P07" autor="U03" stars="5"/>
            <avaliacao produto="P08" autor="U01" stars="4"/>
            <avaliacao produto="P09" autor="U01" stars="2"/>

        </avaliacoes>

这只是我的XML示例,原始版本是400行。

基本上我的问题是,我试图平均给出某个产品的星星,然后对平均大于2星的产品进行分类。

现在我的XHTML输出是:

5 3 5 5 4 

而不是:

5 5 5 4 3

我的XSLT出了什么问题?

1 个答案:

答案 0 :(得分:1)

您的xsl:for-each位于匹配produto的模板中,但它所要做的就是选择完全相同的(单个)产品,因此无需排序。

要进行排序,您应该在首先选择produto的代码中执行此操作。 (你实际上没有)

但为了简单起见,请考虑使用密钥来查找avaliacao元素。

<xsl:key name="avaliacao" match="avaliacao" use="@produto" />

然后你可以xsl:apply-templates选择produto,可以同时进行排序和过滤......

<xsl:apply-templates select="//produto[sum(key('avaliacao', @id)/@stars) div count(key('avaliacao', @id)) gt 2]">
    <xsl:sort select="sum(key('avaliacao', @id)/@stars) div count(key('avaliacao', @id))" order="descending" />
</xsl:apply-templates>

试试这个XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xhtml" encoding="UTF-8" indent="yes"
            doctype-public="-//W3C//DTD XHTML 1.1//EN"
            doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" />

    <xsl:key name="avaliacao" match="avaliacao" use="@produto" />

    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt">
            <head>
                <title>teste</title>
            </head>
            <body>
                <xsl:apply-templates select="//produto[sum(key('avaliacao', @id)/@stars) div count(key('avaliacao', @id)) gt 2]">
                    <xsl:sort select="sum(key('avaliacao', @id)/@stars) div count(key('avaliacao', @id))" order="descending" />
                </xsl:apply-templates>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="produto">
        <xsl:variable name="nr" select="count(key('avaliacao', @id))"/>
        <xsl:variable name="stars" select="sum(key('avaliacao', @id)/@stars)"/>
        <xsl:variable name="media" select="$stars div $nr"/>

        <xsl:value-of select="$media"/>
    </xsl:template>
</xsl:stylesheet>