为什么'child'和'descendant'在这个domdocument()查询中给出相同的结果?

时间:2011-09-05 19:00:21

标签: php xpath domdocument

我正在尝试从以下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("<p>prices</p>");
echo("<pre>");
print_r($prices);
echo("</pre>");

?>

分配给$ prices_nodeList的xpath查询

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

似乎做我想要的,但我不认为我理解它是如何工作的。据我所知,它说“获取所有直接的子元素链接与类”细节“。但是后两个链接中的文字不是直接的孩子,所以我不确定为什么我不必使用

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

这个(即$ prices_nodeList的第一个注释掉的值)也检索所有三个值。我想知道为什么他们都工作,我的查询是否真的是最好的方法。相比之下

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

也有效,但

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

只检索第一个值($ 2,697.75)而不是后两个(因为文本包含在元素中)。

2 个答案:

答案 0 :(得分:2)

  

据我所知,它说'获取所有直接的子元素链接与类“细节”。

不,这意味着获取所有具有当前上下文节点的子类“详细信息”的链接

上下文节点是上一步选择的节点。

///descandant-or-self::node的快捷方式。来自specification

  

///descendant-or-self::node()/的缩写。例如,//para/descendant-or-self::node()/child::para的缩写,因此将选择文档中的任何para元素(即使作为文档元素的para元素也将由//para选择文档元素节点是根节点的子节点); div//paradiv/descendant-or-self::node()/child::para的缩写,因此会选择para个孩子的所有div个后代。

/descendant-or-self::node()基本上选择每个节点。因此,查看childdescendant轴之间没有区别。

如果一个链接不是一个节点的子节点,那么它肯定是其后代之一的子节点,它也由//选择。

答案 1 :(得分:1)

在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::