【问题标题】:Delete Parent node keeping all its child elements in nested XML with PHP删除父节点,使用 PHP 将其所有子元素保留在嵌套 XML 中
【发布时间】:2017-03-02 09:07:35
【问题描述】:

我有嵌套的 XML,我想只删除 xml 文档中的父节点 保留其所有子节点。

<root>
  <items>
    <Product>
       <name> </name>
       <size> </size>
       <images>
          <img1></img1>
          <img2></img2>  
       </images>
    </Product>
    <Product>
       <name> </name>
       <size> </size>
       <images>
          <img1></img1>
          <img2></img2>  
       </images>
    </Product>  
  </items>
</root> 

预期输出 -

<root>
    <Product>
       <name> </name>
       <size> </size>
       <images>
          <img1></img1>
          <img2></img2>  
       </images>
    </Product>
    <Product>
       <name> </name>
       <size> </size>
       <images>
          <img1></img1>
          <img2></img2>  
       </images>
    </Product>  
</root>  

我已经研究并尝试了很多,在删除 节点时,它的所有子节点也会被删除。如果有任何方法使用 DOMDocument 或 php 中的任何其他方式,请提供帮助。

【问题讨论】:

  • 虽然这里是item 节点的$firstChild 属性中的一个有效节点,并在item 之前插入子节点。之后删除它。
  • @ThW 如果我将在 之前插入新子节点,那么我将如何再次删除该新节点。我不想更改节点的名称,而是将其删除并希望 节点直接位于 节点下。

标签: php xml domdocument


【解决方案1】:

嗯,Geza Boems 的回答并不完全符合我的意思。使用 Xpath,您可以获取 items 节点进行迭代。这是一个稳定的结果,因此您可以在修改 DOM 时对其进行迭代。

$document = new DOMDocument();
$document->loadXML($input);
$xpath = new DOMXpath($document);

foreach ($xpath->evaluate('//items') as $itemsNode) {
  // as long that here is any child inside it
  while ($itemsNode->firstChild instanceof DOMNode) {
    // move it before its parent
    $itemsNode->parentNode->insertBefore($itemsNode->firstChild, $itemsNode);
  }
  // remove the empty items node
  $itemsNode->parentNode->removeChild($itemsNode);
}
echo $document->saveXML();

【讨论】:

    【解决方案2】:

    正如@ThW 所说,您必须收集ITEMS 中的子节点,然后将它们插入ROOT,最后删除ITEMS。

    $input = "
    <root>
     <items>
      <Product>
       <name> </name>
       <size> </size>
       <images>
        <img1></img1>
        <img2></img2>  
       </images>
      </Product>
      <Product>
       <name> </name>
       <size> </size>
       <images>
        <img1></img1>
        <img2></img2>  
       </images>
      </Product>
     </items>
    </root>";
    
    $doc = new DOMDocument();
    $ret = $doc->loadXML($input);
    $root = $doc->firstChild;
    $nodes_to_insert = array();
    $nodes_to_remove = array();
    foreach($root->childNodes as $items) {
        if($items->nodeName != "items") {
            continue;
        }
        $nodes_to_remove[] = $items;
        foreach($items->childNodes as $child) {
            if($child->nodeType != XML_ELEMENT_NODE) {
                continue;
            }
            $nodes_to_insert[] = $child;
        }
    }
    foreach($nodes_to_insert as $node) {
        $root->appendChild($node);
    }
    foreach($nodes_to_remove as $node) {
        $root->removeChild($node);
    }
    var_dump($doc->saveXML());
    

    此代码将搜索根目录中的所有“项目”标签,而不仅仅是一个。在“items”里面,它会搜索所有正常的节点(ELEMENT类型,但没有TEXT节点等) 最后一行有一个转储,但由于 XML 标题行,通常您不会在浏览器中看到任何内容。但是如果你看一下页面源,就会显示结果。

    PS:走路的时候不要修改xml结构是很重要的。这就是为什么我只先收集,然后是插入和删除操作。

    【讨论】:

      猜你喜欢
      • 2021-06-11
      • 1970-01-01
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-18
      • 2014-11-18
      相关资源
      最近更新 更多