Получение узла с наибольшим значением с использованием XPath - PullRequest
3 голосов
/ 17 июня 2011

Как в XPath получить узел с наибольшим значением? например

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

вернул бы $ 24,00.

Я использую PHP DOM, так что это будет XPath версии 1.0.

Ответы [ 3 ]

2 голосов
/ 17 июня 2011

Я провожу последнее время, пытаясь придумать для вас самое элегантное решение. Как вы знаете, 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 и документ XSL, который использует функцию math: max из exslt.org , но я попробовал это и не смог заставить его работать правильно из-за знаки доллара ($).

Я протестировал оба решения, и они хорошо сработали для меня.

2 голосов
/ 17 июня 2011

Прежде всего, было бы крайне сложно или невозможно написать один запрос XPath, чтобы получить наибольшее значение, которое содержит символы, отличные от цифр, как в вашем случае $. Но если вы рассматриваете фрагмент XML, исключая $, например

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

тогда вы можете написать один запрос XPath для получения узла с наибольшим значением. //tr/td[not(preceding-sibling::td/text() > text() or following-sibling::td/text() > text())]

Этот запрос возвращает вас <td> со значением 24.00.

Надеюсь, это поможет.

1 голос
/ 17 июня 2011

Чистое решение XPath 1.0 сложно: на уровне XSLT вы будете использовать рекурсию, но это включает в себя написание функций или шаблонов, поэтому оно исключает чистый XPath.В PHP я просто извлекал бы все данные обратно в основной язык и вычислял max (), используя код PHP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...