PHP XPath - 查询找到太多节点

时间:2014-07-09 15:15:50

标签: php xml xpath domdocument

我正在尝试将一行(使用data-id='first')从模板中复制三次,并使用某个值填充正确的字段({first})(在这种情况下为0,1,2)。您可以在下面找到我的简单代码。我不明白,为什么这一行 - $nodeList = $xpath->query("//*[text()[contains(.,'first')]]", $newNode);找到多个节点(它找到包含文本'first'的节点)。它只找到两个行 - 克隆和原始行,所以它替换了它们中的文本,而它应该只替换它们 - 请注意我为函数{{1}提供了第二个参数这应该使搜索相对于我刚刚克隆的新节点。

这是一个小提琴:https://eval.in/170941

HTML:

$xpath->query

PHP:

<html>
    <head>
        <title>test</title>
    </head>
    <body>
        <table>
            <tr data-id="first">
                <td>{first}</td>
            </tr>
        </table>
    </body>
</html>

如您所见,结果是一个三元素表,其行值为0,0,0,而期望值应为0,1,2。

2 个答案:

答案 0 :(得分:1)

使用/启动xpath位置路径意味着它从文档根开始。所以//*始终是任何元素节点,上下文参数无效。

尝试:

$nodeList = $xpath->query(".//*[text()[contains(.,'first')]]", $newNode);

提示:DOMXpath :: query()只允许返回节点列表的表达式,DOMXpath :: evaluate()允许所有表达式。示例:count(//*)

提示:DOMNodelist对象实现迭代器,您可以使用foreach迭代它们。

答案 1 :(得分:1)

您遇到的问题是您正在克隆原始节点,但在第一次通过时,您需要更改原始节点的内容。之后的每次传递都是复制已修改的节点,因此无法找到{first}

一种解决方案是复制您从未插入到文档中的源元素,并在循环中使用它。

这是我的小提琴:https://eval.in/171149

<?php

$html = '<html><head><title>test</title></head><body><table><tr data-id="first"><td>{first}</td></tr></table></body></html>';


$dom = new DOMDocument();

$dom->loadHTML($html);

$xpath = new DOMXPath($dom);

$element = $xpath->query("//*[@data-id='first']")->item(0);
$element->removeAttribute("data-id");

$parent = $element->parentNode;
$clonedNode = $element->cloneNode(true);

for ($i = 0; $i < 3; $i++) {

    $newNode = $clonedNode->cloneNode(true);

    $parent->insertBefore($newNode, $element);

    $nodeList = $xpath->query("//*[text()[contains(.,'first')]]", $newNode);

    for($j = 0; $j < $nodeList->length; $j++) {
        $n = $nodeList->item($j);
        $n->nodeValue = preg_replace("{{first}}", $i, $n->nodeValue);
    }

}

$parent->removeChild($element);



echo $dom->saveHTML();