Search code examples
phpxmlsimplexml

Php xml, replace node in use with an xml object


I'm facing an Xml problem. Probably something stupid but I can't see it...

Here is my Xml at start :

<combinations nodeType="combination" api="combinations">
    <combination xlink:href="http://localhost:8888/vmv/ps/api/combinations/1">
        <id><![CDATA[1]]></id>
    </combination>
    <combination xlink:href="http://localhost:8888/vmv/ps/api/combinations/2">
        <id><![CDATA[2]]></id>
    </combination>
</combinations>

So for each node, I make the API call then I want to replace the node by the returned value, like that :

$c_index = 0;
foreach($combinations->combination as $c){
    $new = apiCall($c->id); //load the new content
    $combinations->combination[$c_index] = $new;
    $c_index++;
}

If I dump the $new into the foreach, I got an simplexmlobject which is fine but if I dump the $combinations->combination[$x], I've got big string of blank...

I'd like to get :

<combinations nodeType="combination" api="combinations">
    <combination xlink:href="http://localhost:8888/vmv/ps/api/combinations/1">
        <my new tree>
            ....
        </my new tree>
    </combination>
    <combination xlink:href="http://localhost:8888/vmv/ps/api/combinations/2">
        <my new tree>
            ....
        </my new tree>
    </combination>
</combinations>

I must be missing something but what...? That's the question...

thanks for your help !


Solution

  • You can change the current element $c of the foreach iteration by making use of a so called SimpleXMLElement-self-reference. By the magic nature of the SimpleXMLElement the entry for both array-access or property access of the number 0 (zero) represents the element itself. This can be used to change the elements value for example:

    foreach ($combinations->combination as $c) {
        $new  = apiCall($c->id); //load the new content
        $c[0] = $new;
    }
    

    The important part is $c[0] here. You could also write $c->{0} for property access with numbers. Example output (may api call returns "apiCall($paramter)" as string):

    <combinations nodeType="combination" api="combinations">
        <combination xlink:href="http://localhost:8888/vmv/ps/api/combinations/1">apiCall('1')</combination>
        <combination xlink:href="http://localhost:8888/vmv/ps/api/combinations/2">apiCall('2')</combination>
    </combinations>
    

    The example in full:

    $buffer = <<<XML
    <root xmlns:xlink="ns:1">
        <combinations nodeType="combination" api="combinations">
            <combination xlink:href="http://localhost:8888/vmv/ps/api/combinations/1">
                <id><![CDATA[1]]></id>
            </combination>
            <combination xlink:href="http://localhost:8888/vmv/ps/api/combinations/2">
                <id><![CDATA[2]]></id>
            </combination>
        </combinations>
    </root>
    XML;
    
    
    function apiCall($string)
    {
        return sprintf('apiCall(%s)', var_export((string)$string, true));
    }
    
    $xml = simplexml_load_string($buffer);
    
    $combinations = $xml->combinations;
    
    foreach ($combinations->combination as $c) {
        $new  = apiCall($c->id); //load the new content
        $c[0] = $new;
    }
    
    $combinations->asXML('php://output');