代码之家  ›  专栏  ›  技术社区  ›  letmaik

查找同级dateTime节点的最小/最大值的最短XPath

  •  1
  • letmaik  · 技术社区  · 16 年前

    我有以下简单的xml:

    <root>
     <item>
      <d>2002-05-30T09:00:00</d>
     </item>
     <item>
      <d>2005-05-30T09:00:00</d>
     </item>
     <item>
      <d>2003-05-30T09:00:00</d>
     </item>
    </root>
    

    我目前的解决方案是:

    /root/item[not(number(translate(./d, 'TZ:-', '.')) <= number(translate(following-sibling::item, 'TZ:-', '.')))][not(number(translate(./d, 'TZ:-', '.')) <= number(translate(preceding-sibling::item, 'TZ:-', '.')))][1]/d
    

    它的工作,但是丑陋的地狱,不是很有效率。基本上,它将dateTime转换为一个数字,然后相互比较。我把这个改编自 here

    最好的方法是什么?

    干杯

    近地天体

    3 回复  |  直到 16 年前
        1
  •  12
  •   user357812 user357812    16 年前

    如果您事先不知道 item 因为每个函数都有一个no node set参数,所以将其参数转换为节点集中的第一个节点,并且顺序比较运算符不能处理字符串。

    max(/root/item/d/xs:dateTime(.))
    
        2
  •  2
  •   LarsH    16 年前

    @neo,您列出的XPath表达式 不起作用

    <root>
       <item>
          <d>2003-05-30T09:00:00</d>
       </item>
       <item>
          <d>2002-05-30T09:00:00</d>
       </item>
       <item>
          <d>2005-05-30T09:00:00</d>
       </item>
    </root>
    

    XPath生成 2003-05-30T09:00:00 ,这显然不是最大值。

    Converting a nodeset to a string ignores all nodes except the first one in document order.

    此外, translate(./d, 'TZ:-', '.') 给你的结果是 2003.05.30.09.00.00 . 这不是一个有效的数字,超过了“5”。你的测试数据之所以有效是因为年份不同。你会得到更好的结果 translate(./d, 'TZ:-', '') 20030530090000 .

    Alejandro说在XPath1.0中不可能做到这一点,他可能是对的。让我们试试看,也许我们会学到一些东西,即使我们不成功。

    接下来,我将尝试在translate函数之外使用常规比较,以便它可以比较整个节点集。类似这种天真的尝试:

    /root/item[
        not(following-sibling::item[
             translate($current/d, 'TZ:-', '') &lt;= translate(./d, 'TZ:-', '')])
        and not(preceding-sibling::item[
             translate($current/d, 'TZ:-', '') &lt;= translate(./d, 'TZ:-', '')])]
    

    (我似乎还记得\XSLT的一些实现,比如MSXML,允许您使用扩展的特性,如 current(1) current() 不是XPath。)

    在这一点上,我同意Alejandro的观点,即在纯标准XSLT1.0中是不可能的。

    如果您有XQuery 1.0,它应该支持XPath 2.0,因此您可以使用Alejandro的解决方案,使用doc()访问您的输入XML文档:

    max(doc("myInput.xml")/root/item/d/xs:dateTime(.))
    
        3
  •  0
  •   msanford    9 年前

    <root>
     <items>
      <item>
       <d>2002-05-30T09:00:00</d>
      </item>
     </items>
     <items>
      <item>
       <d>2005-05-30T09:00:00</d>
      </item>
     </items>
     <items>
      <item>
       <d>2005-05-30T10:00:00</d>
      </item>
     </items>  
    </root>