具有最新日期的XPATH选择条件

时间:2013-08-22 07:40:00

标签: xml xslt xpath

我有以下XML:

<STATUSLIST>
    <STATUS>
        <TYPE VALUE="1"/>
        <DATE>19910000</DATE>
    </STATUS>
    <STATUS>
        <TYPE VALUE="1"/>
        <DATE>19470000</DATE>
    </STATUS>
    <STATUS>
        <TYPE VALUE="2"/>
        <DATE>19470000</DATE>
    </STATUS>
</STATUSLIST>

我希望STATUSTYPE/@VALUE = '2'not(//STATUSLIST/STATUS/DATE > DATE)匹配。 在这种情况下,它将是第3 STATUS

当我应用具有最新日期的类型时,我什么也得不到,因为它不能同时匹配。我想要的是首先匹配TYPE/@VALUE = '2'并在该匹配中获得具有最新日期的那个。

有任何线索吗?

干杯,

聪岛

3 个答案:

答案 0 :(得分:1)

我的解决方案:STATUS[TYPE/@VALUE = '2'][not(//STATUSLIST/STATUS[TYPE/@VALUE = '2']/DATE > DATE)]

答案 1 :(得分:0)

如果我理解你想要什么,由于缺少最大功能,你不能在XPath v1中完成所有这些操作。因此,获取具有所需TYPE的所有STATUS元素:

/STATUSLIST/STATUS[TYPE/@VALUE=2]

然后在调用环境中排序或最大化函数。

答案 2 :(得分:0)

虽然您自己的STATUS[TYPE/@VALUE = '2'][not(//STATUSLIST/STATUS[TYPE/@VALUE = '2']/DATE > DATE)]解决方案可行,但对于大量条目并不是特别有效,因为您要将每个STATUS与其他STATUS进行比较,因此O(N 2 )。更高效的是将它实现为尾递归函数(正如你所说的那样使用XSLT 2.0),如下所示:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
                xmlns:local="urn:local" exclude-result-prefixes="local">

  <xsl:function name="local:latestByDate" as="item()*">
    <xsl:param name="seq" as="item()*"/>
    <xsl:sequence select="local:latestByDate($seq, ())" />
  </xsl:function>

  <xsl:function name="local:latestByDate" as="item()*">
    <xsl:param name="seq" as="item()*" />
    <xsl:param name="maxSoFar" as="item()*" />
    <xsl:choose>
      <xsl:when test="$seq">
        <!-- calculate the new maxSoFar, comparing the current max with
             the first item in $seq.  Note the use of not(x<=y) instead of
             x>y, so the test is true if $maxSoFar is the empty sequence -->
        <xsl:variable name="newMax"
                      select="if(not($seq[1]/DATE &lt;= $maxSoFar/DATE))
                              then $seq[1] else $maxSoFar"/>
        <xsl:sequence select="local:latestByDate(
                                 $seq[position() gt 1], $newMax)" />
      </xsl:when>
      <xsl:otherwise>
        <!-- we have reached the end of $seq, return the max -->
        <xsl:sequence select="$maxSoFar" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:function>

  <!-- example of how to call the function -->
  <xsl:template match="/*">
    <xsl:copy-of select="local:latestByDate(STATUS[TYPE/@VALUE='2'])" />
  </xsl:template>
</xsl:stylesheet>

此函数对节点列表进行单次传递(因此为O(N)),跟踪输入序列中哪个元素具有最新DATE的每一步。