почему 'child' и 'Потомок' дают одинаковый результат в этом запросе domdocument ()? - PullRequest
2 голосов
/ 05 сентября 2011

Я пытаюсь получить текст из ссылок в следующем HEREDOC.

$html = <<<EOT
<a class="details" href="/link.asp">$2,697.75</a>
<a class="details" href="/link.asp"><s>$150.00</s></a>
<a class="details" href="/link.asp"><font color="red" size="2"><b>Price: $125.00</b></font></a>
EOT;
libxml_use_internal_errors(true);

$dom = new DOMDocument();
$dom->loadhtml($html);
$xpath = new DOMXPath($dom);

$prices_nodeList = $xpath->query('//child::a[@class="details"]');
//$prices_nodeList = $xpath->query('//descendant::a[@class="details"]');
//$prices_nodeList = $xpath->query('//a[@class="details"]/descendant::text()');   

foreach ($prices_nodeList as $price) {
    $prices[] = $price->nodeValue;
}

echo("prices");
echo("");
print_r($prices);
echo("
");?>

Запрос xpath, назначенный $ values_nodeList

$prices_nodeList = $xpath->query('//child::a[@class="details"]');

, кажется, делает то, что я хочу, но я не думаю, что понимаю, как это работает. Насколько я понимаю, он говорит: «получить все прямые дочерние элементы ссылок с классом« детали »».Однако текст в последних двух ссылках не является прямым потомком, поэтому я не уверен, почему мне не нужно использовать

$prices_nodeList = $xpath->query('//descendant::a[@class="details"]');

This (то есть первое закомментированное значение $ values_nodeList)также извлекает все три значения. Мне интересно, почему они оба работают, и действительно ли мой запрос является лучшим способом сделать это. В отличие от этого

$prices_nodeList = $xpath->query('//a[@class="details"]/descendant::text()');

работает также, но

$prices_nodeList = $xpath->query('//a[@class="details"]/child::text()');

извлекает только первое значение (2 697,75 долл. США), а не последние два (поскольку текст содержится внутри элементов).

Ответы [ 2 ]

2 голосов
/ 06 сентября 2011

Насколько я понимаю, там написано "получить все прямые дочерние элементы ссылок с классом" детализация "."

Нет, это означает, получить все ссылки с классом "details", которые являются дочерними элементами текущего узла контекста .

Узлы контекста - это те, которые были выбраны на предыдущем шаге.

// является сокращением для /descandant-or-self::node. Из спецификации :

// - это сокращение от /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 детей.

/descendant-or-self::node() в основном выбирает каждый узел. Поэтому нет никакой разницы между осью child или descendant.

Если ссылка не является дочерней по отношению к одному узлу, она, несомненно, является дочерней по отношению к одному из его потомков, который также выбирается с помощью //.

1 голос
/ 06 сентября 2011

В XPath псевдооператор // (сокращение от оси descendant-or-self::) используется для выбора всех узлов определенного типа, где бы они ни находились в дереве ввода. Тогда:

//child::a совпадает с //a

и

//descendant::a по-прежнему эквивалентно //a

Вы всегда выбираете все a узлы в документе, везде, где они есть.


В то время как:

//a/descendant::text(), что равно //a//text(), означает выделение всех потомков текстовых узлов любого a и отличается от

//a/child::text(), что равно //a/text(), и означает выбрать все дочерние текстовые узлы любого a (* $2,697.75 только является дочерним для a , остальные текстовые узлы являются потомками).


В XPath явные оси descendant-or-self:: и child:: используются редко и необходимы. Первый обычно заменяется на //. Второй неявно применяется в / или // как /child:: или //child::.

...