如何选择2个已知XPath之间的所有DOM节点?
Xpath1 = html/body/div[2]/p
Xpath2 = html/body/div[2]/p/a[3]
DOM结构:
<html>
<body>
<div id="id3">
<p id="p3">
text1
<a href="#">
goal
</a>
text2
<a href="#">
Crowdrise
</a>.
</p>
</div>
</body>
</html>
分析器:
$dom = new DOMDocument();
$dom->loadHTML($domain);
$x = new DOMXPath($dom);
$el = $x->query("....??");
因此,基本上寻找一种查询方法来选择两个XPath之间的所有节点。 我看到了几个类似的问题,但它们似乎与XSLT案例有关。
答案 0 :(得分:1)
好问题。 没有通用的方法,因为它取决于第二个元素相对于第一个元素的位置。我的意思是,如果第二个元素是第一个元素的后代,或者它是另一个分支的后代 - 那两个元素完全不同。 所以我们需要做一个假设:
我们的目标是获得第一个元素的所有后代元素(没有文本节点)而没有第二个元素的共享后代。
要实现这一点,我们需要一个表达式:
el1 = All element 1 descendants.
el2 = All element 2 descendants including self.
result = el1 [position() <= count( el1 ) - count( el2 )]
正如您所看到的,我们正在构建一组前N个元素,直到我们到达第二个元素。
以下是一个例子:
<?php
$dom = new DOMDocument();
$dom->loadHTML('<html>'
. ' <body>'
. ' <div>'
. ' <h1>shlomi</h1>'
. ' <p>'
. ' <span>goal1</span>'
. ' text1'
. ' <a href="#">goal2</a>'
. ' text2'
. ' <a href="#"><span></span>Crowdrise</a>'
. ' .'
. ' </p>'
. ' </div>'
. ' </body>'
. ' </html>');
$x = new DOMXPath($dom);
$path1 = "/html/body/div/p/descendant::*"; // all descendant elements without text
$path2 = "/html/body/div/p/a[2]/descendant-or-self::*"; // all descendant elements without text including self
$path3 = $path1."[position() <= count(".$path1.") - count(".$path2.")]";
$elList = $x->query($path3);
foreach ($elList as $node) {
echo $node->nodeName." -> text: ".$node->textContent."<br />";
}
这将打印:
span -> text: goal1
a -> text: goal2
注意我使用*
仅定位没有文字节点的元素 - 如果您希望所有节点都将其替换为node()
。