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);
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();
Edit: PHP 8 got several new DOM standard methods. One of them is remove()
:
$document = new DOMDocument;
$document->loadxml($xmlString);
$xpath = new DOMXPath($document);
foreach ($xpath->evaluate("//content[@id='abc123']/parent::*") as $node) {
// new shortcut method
$node->remove();
}
echo $document->saveXml();