【问题标题】:How to sort, and then pick one item如何排序,然后选择一项
【发布时间】:2012-10-26 11:43:00
【问题描述】:

我正在使用 XSLT 从提要中获取数据。目前我使用这个block of code,它只是从提要中挑选出第一个项目。我对其进行了一些更改,因此它适用于此示例 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”。

【问题讨论】:

    标签: xml xslt sorting


    【解决方案1】:

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

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

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

    (谓词为:“选择任何&lt;price&gt; 不低于任何一本书的&lt;book&gt;。”)

    这将在sample XML 中选择&lt;author&gt;Galos, Mike&lt;/author&gt;

    注意事项

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

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

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

    • XPath 自动将 “小于/大于(或等于)” 类型的两个操作数强制转换为 numbers。只要&lt;price&gt;的值可以直接转换为数字,上面的表达式就成功了。

    • 一定是逆逻辑("not(lower than any)"),因为永远不可能相反的("greater than any")真(而 “大于或等于任何” 始终为真)。

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

    【讨论】:

      【解决方案2】:

      您可以在 apply-templates 中指定 &lt;xsl:sort&gt;,如下所示:

      <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>
      

      然后在您的小“书”模板中,使用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>
      

      【讨论】:

      • 正是我想要的。我的第二个问题是如何从排序列表中过滤第二个项目,但它也得到了回答。谢谢!
      【解决方案3】:

      你需要并且使用 position 函数只返回第一个:

      <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>
      

      【讨论】:

      • position()=first() 等价于position()=1,只是更长。
      猜你喜欢
      • 2015-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-05
      • 2021-11-21
      • 1970-01-01
      相关资源
      最近更新 更多