0

I need to remove some elements that match specific strings on an XML using PHP, I guess I can do this with DOM as I have been reading. The problem comes using multiple strings.

I have this XML:

<?xml version="1.0" encoding="utf-8"?>
<products>
  <item>
    <reference>00001</reference>
    <other_string>PRODUCT 1</other_string>
    <brand>BRAND 1</brand>
  </item>
  <item>
    <reference>00002</reference>
    <other_string>PRODUCT 2</other_string>
    <brand>BRAND 2</brand>
  </item>
  <item>
    <reference>00003</reference>
    <other_string>PRODUCT 3</other_string>
    <brand>BRAND 3</brand>
  </item>
  <item>
    <reference>00004</reference>
    <other_string>PRODUCT 4</other_string>
    <brand>BRAND 4</brand>
  </item>
  <item>
    <reference>00005</reference>
    <other_string>PRODUCT 5</other_string>
    <brand>BRAND 5</brand>
  </item>
</products>

And I need to remove the elements that match the strings "BRAND 3 and BRAND 4" on the <brand></brand> tag and get an XML similar to this

<?xml version="1.0" encoding="utf-8"?>
<products>
  <item>
    <reference>00001</reference>
    <other_string>PRODUCT 1</other_string>
    <brand>BRAND 1</brand>
  </item>
  <item>
    <reference>00002</reference>
    <other_string>PRODUCT 2</other_string>
    <brand>BRAND 2</brand>
  </item>
  <item>
    <reference>00005</reference>
    <other_string>PRODUCT 5</other_string>
    <brand>BRAND 5</brand>
  </item>
</products>

Any help will be highly appreciated.

  • use xpath to get all `brand` tags. check their content against your filter rules. if they match, go up to `item` and delete the item – Sindhara Mar 15 '19 at 20:21

2 Answers2

1

Again using XPath, but this time use it to do the filtering of the nodes your after as well and then remove them...

$xml = simplexml_load_file("data.xml");

$remove = $xml->xpath("//item[brand='BRAND 3' or brand='BRAND 4']");
foreach ( $remove as $item )    {
    unset($item[0]);
}

The XPath //item[brand='BRAND 3' or brand='BRAND 4'] is simply looking for any <item> element which has a <brand> element which contains BRAND 3 or BRAND 4. This then loops over the matches and removes them. Using $item[0] is a fudge to unset the XML element rather than unsetting the variable that is being used.

Nigel Ren
  • 56,122
  • 11
  • 43
  • 55
0

The hardest part is to remove the elements. Therefore you can have a look at this answer

first get all brands with xPath('//brand'). then remove the items which match your filter rule.

$sXML = simplexml_load_string($xml);
$brands = $sXML->xPath('//brand');

function filter(string $input) {
    switch ($input) {
        case 'BRAND 3':
        case 'BRAND 4':
            return true;
        default:
            return false;
    }
}

array_walk($brands, function($brand) {
    $content = (string) $brand;
    if (filter($content)) {
        $item = $brand->xPath('..')[0];
        unset($item[0]);
    }
});

var_dump($sXML->asXML());
Sindhara
  • 1,423
  • 13
  • 20
  • This works perfect but this have a problem with whitespaces because the code leave one where element were removed. I'm trying to solve it. Thanks! @kuh-chan – Fernando Olvera Mar 20 '19 at 02:55
  • Solved by @IMsOP https://stackoverflow.com/questions/55253280/remove-white-spaces-between-tag-values-in-xml-with-php – Fernando Olvera Mar 20 '19 at 21:09