我正在尝试将一行(使用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。
答案 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();