如何排序,然后选择一个项目

时间:2012-11-06 13:48:36

标签: xml xslt sorting

我正在使用XSLT从Feed中获取数据。目前我使用此block of code,它只是从Feed中选择第一项。我稍微改了一下,所以它适用于这个示例XML。

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

<xsl:template match="/">
  <html>
  <body>
  <xsl:apply-templates/> 
  </body>
  </html>
</xsl:template>

<xsl:template match="/">
  <xsl:value-of select="catalog/book/author"/>
</xsl:template>

</xsl:stylesheet>

我想按价格对xml进行排序,然后选择与价格最高的图书相关联的作者。我尝试过各种各样的东西,但我似乎无法弄明白。

目前的输出是“Gambardella,Matthew”,但我需要它是“Galos,Mike”。

3 个答案:

答案 0 :(得分:3)

  

我想按价格对xml进行排序,然后选择与价格最高的图书相关联的作者。

FWIW,你也可以用纯XPath做到这一点。

/catalog/book[not(price < /catalog/book/price)]/author

(谓词上写着:“选择<book>不低于任何图书的任何<price>。”

这会在sample XML中选择<author>Galos, Mike</author>

注释

  • 此表达式不会选择 最高价格的书籍,而是所有最高价格的书籍(即,如果有两本书,它会选择两本书同样的价格)。使用

    /catalog/book[not(price < /catalog/book/price)][1]/author
    

    选择一本匹配的书(将选择文档顺序中的第一本书)。

  • XPath会自动强制“少于/大于(或等于)”类型与numbers进行比较的两个操作数。只要<price>的值可以直接转换为数字,上述表达式就会成功。

  • 它必须是反逻辑(“not(低于任何)”),因为相反的(“大于任何”)永远不会是是的(而“大于或等于任何”总是如此)。

  • nodeset1[expression < nodeset2]操作的时间复杂度为:
    O(count(nodeset1)×count(nodeset2)) 在上述情况nodeset1nodeset2相同,因此有效时间复杂度为:
    O(n²)
    换句话说,它不是解决这个问题的最有效方法(我会说<xsl:apply-templates><xsl:sort>是),但另一方面 - 它是一个单行,很可能是对你来说足够快。

答案 1 :(得分:1)

您可以在apply-templates中指定<xsl:sort>,如下所示:

<xsl:template match="/">
    <html>
        <body>
            <xsl:apply-templates select="/catalog/book">
                <xsl:sort select="price" order="descending" data-type="number"/>
            </xsl:apply-templates>
        </body>
   </html>
</xsl:template>

然后在您的小'book'模板中,使用position()过滤掉第一个图书节点

<xsl:template match="book">
    <xsl:if test="position() = 1">
        <xsl:value-of select="author"/>
        <br/>
        <xsl:value-of select="price"/>
    </xsl:if>
</xsl:template>

答案 2 :(得分:0)

您需要并使用位置功能仅返回第一个:

<xsl:template match="/">
    <html>
        <body>
            <xsl:apply-templates select="/catalog/book">
                <xsl:sort select="price" order="descending" data-type="number"/>
            </xsl:apply-templates>
        </body>
   </html>
</xsl:template>

<xsl:template match="book">
   <xsl:if test="position()=first()">
       <xsl:value-of select="author"/>
   </xsl:if>
</xsl:template>