我有一个XML,它是一个包含多个range
节点的目录,而这些节点又包含多个item
个节点:
<cat>
<range>
<item>
<a></a>
<b></b>
<c></c>
</item>
<item>
<a></a>
<b></b>
<c></c>
</item>
<item>
<a></a>
<b></b>
<c></c>
</item>
<item>
<a></a>
<b></b>
<c></c>
</item>
<!-- node 'a' need to be added here -->
<b></b>
<d></d>
</range>
<range>
<item>
<a></a>
<b></b>
<c></c>
</item>
<item>
<a></a>
<b></b>
<c></c>
</item>
<!-- node 'a' need to be added here -->
<b></b>
<d></d>
</range>
</cat>
现在,我需要在所有 a
节点之后和节点item
之前的每个范围内添加节点b
。
注意:节点a
&amp; b
内外item
是相同的
我能够在b
内添加range
节点,如下所示:
foreach($dom->getElementsByTagname('range') as $range) {
forearch ($range->getElementsByTagName('d') as $d) {
$b = $dom->createElement('b');
$d = $d->parentNode->insertBefore($b, $d);
}
}
如果我使用相同的代码尝试在所有a
节点之外添加节点item
,那么它将无效,因为引用节点b
与内部相同和外部 item
个节点;所以它只会在a
个节点中添加节点item
。
我找到了insertAfter
函数;
function insertAfter(\DOMNode $newNode, \DOMNode $referenceNode)
{
if($referenceNode->nextSibling === null) {
return $referenceNode->parentNode->appendChild($newNode);
} else {
return $referenceNode->parentNode->insertBefore($newNode, $referenceNode->nextSibling);
}
}
但是它不会给我想要的结果,因为如果我使用item
作为参考节点,它将在第一个item
之后添加新节点,而在之后我需要它 item
个节点。
答案 0 :(得分:1)
实现您尝试做的最简单方法是使用xPath。
$xpath = new DOMXpath($dom);
$bs = $xpath->query("//range/b");
$a = new DOMElement('a');
foreach ($bs as $b) {
$b->parentNode->insertBefore($a, $b);
}
这得到了所有的&#34; b&#34;这是范围的直接孩子而不是其孙子。
答案 1 :(得分:0)
让第一级孩子进行比较,直到找到你想要的孩子($b
)并在其前面插入:
foreach($dom->getElementsByTagname('range') as $range) {
foreach($range->childNodes as $first_level_child) {
if($first_level_child->tagname=='b') {
$a = $dom->createElement('a');
$first_level_child->parentNode->insertBefore($a, $first_level_child);
}
}
}