Home > Mobile >  PHP XML delete node if atrribute
PHP XML delete node if atrribute

Time:07-01

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).

  • Related