0

My xml file looks like this - I want to (simplified for sake of the example ) add 1 to every node value and then check for duplicates. If a duplicate node exists in , I want to remove the parent and then return all with unique as xml.

<?xml version="1.0" encoding="UTF-8"?>
<channel>
<item>
    <gid>1240</gid>
</item>
<item>
    <gid>1440</gid>
</item>
<item>
    <gid>1440</gid>
</item>
<item>
    <gid>246</gid>
</item>

So my desired output would be:

<?xml version="1.0" encoding="UTF-8"?>
<channel>
<item>
    <gid>1241</gid>
</item>
<item>
    <gid>1441</gid>
</item>
<item>
    <gid>247</gid>
</item>

My code looks like this - the manipulation part is solved but I cannot figure out how to check if the new is a duplicate and then remove its parent before returning it as XML. I think that storing all values as an array within the loop is correct but after that I get stuck. Thankful for any help.

<?php

$xmllink = 'items.xml';

header("Content-type: text/xml");

$xml=simplexml_load_file($xmllink) or die("Error: Cannot create object");

$xml->channel;

foreach ($xml as $anything) {

// find the <gid>
$newgid = $anything->gid;

// manipulate <gid>
$anything->gid = $newgid +1;

// store all gid + 1 in array
$allgids[] = $newgid;}

echo $xml->asXML();

?>

1 Answers1

0

SimpleXML isn't very good when you want to change the structure of a document.

But you can do it by a bit of a work round. Firstly, any manipulation on a document is difficult when your trying to iterate over it at the same time. Which is why I've used XPath to get a list of the items and then iterate over that list. If the item is already there, I use unset() to remove it. (Have a more in depth read of Remove a child with a specific attribute, in SimpleXML for PHP for a full answer to how this works).

<?php 
error_reporting(E_ALL);
ini_set('display_errors', 1);

$xmlDoc = <<< XML
<?xml version="1.0" encoding="UTF-8"?>
<channel>
<item>
    <gid>1240</gid>
</item>
<item>
    <gid>1440</gid>
</item>
<item>
    <gid>1440</gid>
</item>
<item>
    <gid>246</gid>
</item>
</channel>
XML;

$xml = simplexml_load_string($xmlDoc);
$allgids = [];
$items = $xml->xpath("//item");
foreach ($items as $item) {

    // find the <gid>
    $newgid = $item->gid;
    // manipulate <gid>
    $item->gid = $newgid +1;
    if ( in_array($newgid, $allgids))   {
        unset($item[0]);
    }
    else    {
        // store all gid + 1 in array
        $allgids[] = (string)$newgid;
    }
}

echo $xml->asXML();

Although in this example I use the code from a string, the same will apply if loading it from a file as you are.

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