douzai1074 2017-11-23 08:48
浏览 22
已采纳

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

I have an XML which is a catalog containing several range nodes which in turn contain several item nodes:

<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>

Now I need to add node a inside each range just after ALL item nodes and just before node b.

NOTE: nodes a & b inside and outside item is the same

I was able to add the b node inside range, like this:

foreach($dom->getElementsByTagname('range') as $range) {
    forearch ($range->getElementsByTagName('d') as $d) {
        $b = $dom->createElement('b');
        $d = $d->parentNode->insertBefore($b, $d);
    }
}

If I use the same code to try and add node a outside all the item nodes, it won't work since the reference node b is the same inside and outside the item nodes; so it will just add node a inside the item nodes.

I found an insertAfter function;

function insertAfter(\DOMNode $newNode, \DOMNode $referenceNode)
{
  if($referenceNode->nextSibling === null) {
      return $referenceNode->parentNode->appendChild($newNode);
  } else {
      return $referenceNode->parentNode->insertBefore($newNode, $referenceNode->nextSibling);
  }
}

but it will not give me the desired result since if I used item as the reference node, it will add the new node just after the first item whereas I need it after all the item nodes.

  • 写回答

2条回答 默认 最新

  • douyue8364 2017-11-23 09:11
    关注

    The easiest way to achieve what you are trying to do is by using xPath.

    $xpath = new DOMXpath($dom);
    $bs = $xpath->query("//range/b");
    $a = new DOMElement('a');
    
    foreach ($bs as $b) {
        $b->parentNode->insertBefore($a, $b);
    }
    

    This gets alls the "b" that are a direct child of range but not its grandchildren.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 需要步骤截图(标签-服务器|关键词-map)
  • ¥50 gki vendor hook
  • ¥15 centos7中sudo命令无法使用
  • ¥15 灰狼算法和蚁群算法如何结合
  • ¥15 这是一个利用ESP32自带按键和LED控制的录像代码,编译过程出现问题,请解决并且指出错误,指导如何处理 ,协助完成代码并上传代码
  • ¥20 stm32f103,hal库 hal_usart_receive函数接收不到数据。
  • ¥20 求结果和代码,sas利用OPTEX程序和D-efficiency生成正交集
  • ¥50 adb连接不到手机是怎么回事?
  • ¥20 抓取数据时发生错误: get_mooncake_data() missing 1 required positional argument: 'driver'的问题,怎么改出正确的爬虫代码?
  • ¥15 vs2022无法联网