【问题标题】:Getting highest value node using XPath使用 XPath 获取最高值节点
【发布时间】:2011-09-16 21:14:21
【问题描述】:

在 XPath 中,如何获取具有最高值的节点?例如

<tr>
   <td>$12.00</td>
   <td>$24.00</td>
   <td>$13.00</td>
</tr> 

将返回 24.00 美元。

我使用的是 PHP DOM,所以这是 XPath 1.0 版。

【问题讨论】:

    标签: php xml dom xpath


    【解决方案1】:

    纯 XPath 1.0 解决方案很困难:在 XSLT 级别,您将使用递归,但这涉及编写函数或模板,因此它排除了纯 XPath。在 PHP 中,我只需将所有数据拉回宿主语言并使用 PHP 代码计算 max()。

    【讨论】:

    • 好的,所以你建议循环遍历 DomNodeList 来构建一个值数组,然后运行 ​​max()?
    • @babonk - 无需创建另一个数组。看看我的第二个解决方案。
    【解决方案2】:

    我花了最后一点时间为你想出最优雅的解决方案。如您所知,max 在 XPath 1.0 中不可用。我尝试了几种不同的方法,其中大多数似乎都不是很有效。

    <?php
    
    $doc = new DOMDocument;
    $doc->loadXml('<table><tr><td>$12.00</td><td>$24.00</td><td>$13.00</td></tr></table>');
    
    function dom_xpath_max($this, $nodes)
    {
      usort($nodes, create_function('$a, $b', 'return strcmp($b->textContent, $a->textContent);'));
    
      return $this[0]->textContent == $nodes[0]->textContent;
    }
    
    $xpath = new DOMXPath($doc);
    $xpath->registerNamespace('php', 'http://php.net/xpath');
    $xpath->registerPHPFunctions('dom_xpath_max');
    
    $result = $xpath->evaluate('//table/tr/td[php:function("dom_xpath_max", ., ../td)]');
    
    echo $result->item(0)->textContent;
    
    ?>
    

    或者,您可以使用foreach 循环遍历更简单的 XPath 表达式的结果(一次只选择所有 TD 元素)并找到最大的数字。

    <?php
    
    ...
    
    $xpath = new DOMXPath($doc);
    
    $result = $xpath->evaluate('//table/tr/td');
    
    $highest = '';
    
    foreach ( $result as $node )
      if ( $node->textContent > $highest )
        $highest = $node->textContent;
    
    echo $highest;
    
    ?>
    

    您还可以使用 XSLTProcessor 类和使用 exslt.org 中的 math:max 函数的 XSL 文档,但我已经尝试过了,但由于美元符号 ($) 的原因,它无法正常工作。

    我已经测试了这两种解决方案,它们对我都很有效。

    【讨论】:

      【解决方案3】:

      首先,编写单个 XPath 查询以返回包含除数字以外的字符的最高值(如您的情况 $)将非常困难或不可能。但是,如果您考虑排除$ 之类的XML 片段

      <tr>
         <td>12.00</td>
         <td>24.00</td>
         <td>13.00</td>
      </tr> 
      

      然后您可以编写单个 XPath 查询来检索最高值节点。 //tr/td[not(preceding-sibling::td/text() &gt; text() or following-sibling::td/text() &gt; text())]

      此查询返回 &lt;td&gt; 和值 24.00

      希望这会有所帮助。

      【讨论】:

      • @babonk - 此解决方案适用于美元符号。我已经发布了一个与美元符号一起使用的 2 个解决方案的答案。
      • @Francois。那是正确的。这不适用于$ 符号。我的回答旨在提供单个 XPath 查询。否则有完成此任务的传统方法(循环/递归)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-17
      • 2016-02-24
      • 2011-08-27
      • 2012-06-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多