Removing nodes in XML using XPath and PHP

I have XML:

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

I would like to find node c id, which abc123u delete <content>and its parent<level>

So, the end result will be:

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

I tried this in PHP with no 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);
+4
source share
3 answers

Here are two questions with your source.

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

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

foreach, , node .

$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();
+2
<?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();

?> 

:

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

This is a kind of hack, but I got it to work with your example. There is probably one problem with your request xpath- pay attention to //at the beginning.

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

// using SimpleXMLElement instead of DOMDocument
$xml = new SimpleXMLElement($xml_string);

// standardize the string version of the xml so str_replace works
$xml_string = $xml->asXML();

// search for the target; note the // at the beginning of the query
$target = $xml->xpath("//content[@id='abc123']/parent::*");

// use simple string replacement to remove the node
echo str_replace($target[0]->asXML(), '', $xml_string);

Not very elegant, but it looks like he took care of your problem.

-2
source

Source: https://habr.com/ru/post/1609055/


All Articles