问题 如何使用XPath选择最后N个元素?


我支持一个生成内容XML的网站,然后使用XSLT将其翻译成网页。我被要求创建一个新的样式表,它将“存档”页面的输出转换为Atom以进行联合。我遇到的问题是存档页面包含相当多的项目 - 142和计数 - 并且Feed应该永远不会有超过30项。

目前,存档页面的输出如下所示:

<archive>
    <year>
        <month>
            <day>
            <day>
            ...
        </month>

        ...
    </year>

    ...
</archive>

year 和 month 标签由HTML转换使用,但与Atom提要完全无关。我原本希望使用 position() 具有后代轴的功能将起作用(//day[position()>last()-30]),但这选择了最后30天 每个月,这根本不是我需要的。 :-)

有没有办法用XSLT或XPath做到这一点?必须修改XML生成器才能添加,比如说 feed="true" 属于过去三十天似乎是一个非常讨厌的kludge。


2712
2018-01-19 18:21


起源

那么你想要哪几天?前30? - scunliffe
对不起,最后30个。这些条目是按时间顺序排列的,所以最近的条目是最后的。 - Ben Blank


答案:


position()/ last()返回当前上下文中的位置/最后位置,因此当导航器位于一个<month>中时,position()将在该月内返回<day>,而last()将返回last <day >那个月内,但我想你知道的。

因此,您可以做的就是将所有<day>的数据展平并放入一个变量,然后再像以前一样进行选择。

<xsl:variable name="days" select="//day"/>
<xsl:apply-templates select="$days[position()>last()-30]" />

10
2018-01-19 18:39



我觉得这很聪明。对这种技术有很多要求吗? - Rob Kennedy
对不起,但我不确定你打电话的意思是什么?如果你的意思是它是一种众所周知的技术,我不这么认为。只是一个创意解决方案! :) - baretta
刚刚发现你可以通过不使用而不创建变量来做到这一点 // 捷径。看到我的回答。 - Ben Blank


浏览 XSLT规范 今天,我找到了一个解释原因的说明 // 表现得这样:

// 是的缩写 /descendant-or-self::node()/。例如, //para 是的缩写 /descendant-or-self::node()/child::para 所以会选择任何一个 para 文件中的元素(甚至是 para 将选择作为文档元素的元素 //para 因为文档元素节点是根节点的子节点); div//para 是的缩写 div/descendant-or-self::node()/child::para 所以将选择所有 para div孩子的后代。

注意: 位置路径 //para[1] 并不意味着与位置路径相同 /descendant::para[1]。后者选择第一个后代 para 元件;前者选择所有后代 para 第一个元素 para 他们父母的孩子。

换句话说,使用时 //position() 是按照计算的 child 轴,而不是 descendant-or-self 轴。指定 descendant 要么 descendant-or-self 允许你获得第一个/最后一个 ñ 您期望的节点:

<xsl:apply-templates select="descendant::day[position()>last()-30]"/>

4
2018-03-31 17:50