使用insertBefore并处理同名XML PHP的几个节点

时间:2017-11-23 08:48:15

标签: php xml

我有一个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个节点。

2 个答案:

答案 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);
        }
    }
}