Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing nodes in XML with XPath and PHP

Tags:

php

xml

xpath

I have an XML:

<root>
   <level name="main">
      <level name="sub_1">
         <content id="abc123" />
      </level>
   </level>
</root>

I would like to search for the node with id that is abc123 and delete the <content> and its parent <level>

So the end result would be:

<root>
  <level name="main">
  </level> 
</root>

I have tried this in PHP without result, what am I doing wrong?

 $doc = new DOMDocument;
 $doc->loadxml($xml_from_file); 
 $xpath = new DOMXPath($doc);
 $node_list = $xpath->query("content[@id='abc123']/parent::*"); 
 $node = $node_list->item(0); 
 $doc->removeChild($node);
like image 796
dr_rk Avatar asked Sep 26 '15 00:09

dr_rk


People also ask

What are nodes in XPath XML?

XPath Terminology. Nodes. In XPath, there are seven kinds of nodes: element, attribute, text, namespace, processing-instruction, comment, and document nodes. XML documents are treated as trees of nodes. The topmost element of the tree is called the root element. Look at the following XML document:

How do I remove a node from an XML file?

The removeChild () method removes a specified node. When a node is removed, all its child nodes are also removed. This code will remove the first <book> element from the loaded xml:

How do I delete the current node in xpathnavigator?

The XPathNavigatorclass provides the DeleteSelfmethod to delete the current node an XPathNavigatorobject is currently positioned on from an XML document. After a node has been deleted using the DeleteSelfmethod, it is no longer reachable from the root of the XmlDocumentobject.

How do I remove a node from the parent node?

Remove the element node by using the removeChild () method from the parent node Remove Myself - Remove the Current Node The removeChild () method is the only way to remove a specified node. When you have navigated to the node you want to remove, it is possible to remove that node using the parentNode property and the removeChild () method:


2 Answers

Here are two issues with your source.

The expression does only match child nodes. You need to start it with // to match any node: //content[@id='abc123']/parent::*.

The found node is not a child of the document so, you need to remove it from its own parent: $node->parentNode->removeChild($node);.

I suggest using a foreach to avoid problems if the node doesn't exists.

$document = new DOMDocument;
$document->loadxml($xmlString); 
$xpath = new DOMXPath($document);

foreach ($xpath->evaluate("//content[@id='abc123']/parent::*") as $node) {
  $node->parentNode->removeChild($node);
}

echo $document->saveXml();
like image 177
ThW Avatar answered Oct 21 '22 05:10

ThW


<?php

$xml_from_file = '<root>
   <level name="main">
      <level name="sub_1">
         <content id="abc123" />
      </level>
   </level>
</root>';

 $doc = new DOMDocument;
 $doc->loadxml($xml_from_file); 
 $xpath_selector = new DOMXPath($doc);
//Here you forget at the begin the //
 $node_list = $xpath_selector->query("//content[@id='abc123']/parent::*"); 
//here you get the reference to the parent of content
 $node = $node_list->item(0); 
//but for remove the child you need to go to the parent node
 $node->parentNode->removeChild($node);
 echo $doc->saveXML();

?> 

Output:

<root>
  <level name="main">
  </level> 
</root>
like image 43
Adrian Cid Almaguer Avatar answered Oct 21 '22 05:10

Adrian Cid Almaguer