I need to delete Node if attribute is not equal to brand="NotDelete" but I don't know why but the code saves itself in the xml file without any changes
XML code:
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0">
<entry>
<title>
Product title
</title>
<link>
Test link
</link>
<condition>
new
</condition>
<availability>
Test ava
</availability>
<inventory>
3
</inventory>
<price>
35
</price>
<brand>
NotDelete
</brand>
</entry>
</feed>
My php code:
<?php
$resp = file_get_contents( 'EXAMPLE.COM' );
$doc = new DomDocument('1.0');
//$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$doc->loadxml( $resp );
$xpath = new DOMXPath($doc);
foreach ($xpath->evaluate("/feed/entry/brand[not(contains(text(), 'NotDelete'))]") as $node) {
$node->parentNode->removeChild($node);
}
$doc->save('test1.xml');
CodePudding user response:
Your XML defines the namespace http://www.w3.org/2005/Atom
for elements without a prefix. Prefixes/aliases are used to avoid repeating an long and complex but unique namespace URI all over the XML. The parser resolves it. The 3 following examples can all be read as <{http://www.w3.org/2005/Atom}feed/>
.
<feed xmlns="http://www.w3.org/2005/Atom"/>
<a:feed xmlns:a="http://www.w3.org/2005/Atom"/>
<atom:feed xmlns:atom"http://www.w3.org/2005/Atom"/>
To address this is Xpath you will have to register a prefix alias for the namespace. Here is no concept of a default namespace in Xpath 1.0. After you register the alias the Xpath processor will resolve it internally. You can think of an expression like this:
/atom:feed
→/{http://www.w3.org/2005/Atom}feed
$document = new DOMDocument();
$document->loadXML(getXML());
$xpath = new DOMXpath($document);
// register an alias for the namespace
$xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');
$expression = "/atom:feed/atom:entry/atom:brand[not(contains(., 'NotDelete'))]";
foreach ($xpath->evaluate($expression) as $node) {
// PHP 8 supports DOM Level 3 methods
$node->remove();
}
$document->formatOutput = TRUE;
echo $document->saveXML();
function getXML() {
return <<<'XML'
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0">
<entry>
<title>Product One</title>
<brand>Delete</brand>
</entry>
<entry>
<title>Product Two</title>
<brand>NotDelete</brand>
</entry>
</feed>
XML;
}
This will delete the brand node. If you would like to remove the entry
element the expression would look a little different:
$expression = "/atom:feed/atom:entry[not(atom:brand[contains(., 'NotDelete')])]";
But here is an additional problem. The Atom Format does not have a brand
element. You example XML might be missing redefinitions of the default namespace. Or it is invalid ATOM (Can still be wellformed XML).