Search code examples
phpxmlsimplexml

PHP - "Duplicate" the value of the addchild function


I'm using PHP with SimpleXML.

It's a bit hard to explain but I was wondering how I could do the following.

I'm checking with the following code if the first parent node exists and if it doesn't exist, I create that node.

 if (!isset($xml->$serialize)){
    $set = $xml->addChild($serialize);
    }
$last = $set;

The same applies for the other nodes which are checked like that:

if (!isset($last->$serialize)){
    $set = $last->addChild($serialize);
}
$last = $set;

If the whole path isn't created yet, it works perfectly fine but if some nodes are already created then it bugs out and creates a weird path. I know why it does that but I have no idea how I should fix it.

The variable $set gets its value from creating a child node and if there is one already created then the code in "if" doesn't run and $set doesn't get a value. How can I do it so even if there is already a child node, the variable $set gets its value? Or how can I "duplicate" the value that you get from the addchild function?

EDIT: I call the xml with the following code:

$xml = new SimpleXMLElement("<permissions></permissions>");

And save it at the end of the application:

$xml->saveXML("/home/atakan/PhpstormProjects/User_Permissions/test.xml");

The output I expect looks like this. I have four variables for example:

  • a/b/c/d
  • a/b/c/e
  • a/b/f
  • g/h

Then the Xml-Output should be like in this picture.


Solution

  • You needed to break down the string into it's individual components and go through adding them one at a time. The code is mostly there, but trying to add it in all in one go isn't going to work.

    I've written it as a function and you can see how it splits the input down by explode and the /. It then checks each level as it goes adding in any missing elements, or if they exist - just adjusting $set to point to the new existing element in the structure.

    <?php
    error_reporting ( E_ALL );
    ini_set ( 'display_errors', 1 );
    
    function addElement ( SimpleXMLElement $start, string $path )    {
        $parts = explode("/", $path);
        $set = $start;
        foreach ( $parts as $part ) {
            if ( !isset($set->$part) )  {
                $set = $set->addChild($part);
            }
            else    {
                $set = $set->$part;
            }
        }
    
    }
    
    $xml = new SimpleXMLElement("<permissions></permissions>");
    addElement( $xml, "a/b/c/d" );
    addElement( $xml, "a/b/c/e" );
    addElement( $xml, "a/b/f" );
    addElement( $xml, "g/h" );
    echo $xml->saveXML();
    

    Echos out...

    <?xml version="1.0"?>
    <permissions>
        <a>
            <b>
                <c>
                    <d />
                    <e />
                </c>
                <f />
            </b>
        </a>
        <g>
            <h />
        </g>
    </permissions>