Question

I have an XML file like this:

<?xml version="1.0"?>
<export>
  <config>
    <Exported Name="test">
      <values>
        <node name="yellow" />
        <node name="green" />
        <node name="red" />
      </values>
    </Exported>
  </config>
</export>

While i know how to add an attribute following the PHP documentation for SimpleXML http://www.php.net/manual/en/simplexmlelement.addattribute.php

What i am not sure if its possible to do is wrap what i have in another tag. Example i want to change above to:

<?xml version="1.0"?>
<main>
   <cust>
       johndoe@gmail.com
   </cust>
   <export>
      <config>
        <Exported Name="test">
          <values>
            <node name="yellow" />
            <node name="green" />
            <node name="red" />
          </values>
        </Exported>
      </config>
   </export>
</main>

So basically what i am doing is creating a new top level node called main and putting a new attribute cust and adding a value and then adding the previous top level node export inside the main node after the cust attribute.

I would ideally like to use simpleXML but i wonder what is the best way to do this, read everything from export, and spit it all back out in a loop, is that the best method to do this or is there a way to just say print all of the export node here rather than pretty much reading the whole XML and having to loop through and rebuild it all just to add 2 new nodes?

Was it helpful?

Solution

This does not work with SimpleXML but with DOMDocument which allows to import nodes recursively from one document to the other. Luckily SimpleXML is just a facade on top of DomDocument in PHP and nodes can be imported from SimpleXML to DOM and then within DOM from one document into the other:

$xml = new SimpleXMLElement('<?xml version="1.0"?>
<export>
  <config>
    <Exported Name="test">
      <values>
        <node name="yellow" />
        <node name="green" />
        <node name="red" />
      </values>
    </Exported>
  </config>
</export>');

$target = new SimpleXMLElement('<?xml version="1.0"?>
<main>
   <cust>
       johndoe@gmail.com
   </cust>
</main>');

$cust = dom_import_simplexml($target->cust);

$cust->parentNode->appendChild(
    $cust->ownerDocument->importNode(dom_import_simplexml($xml), true)
);

$target->asXML('php://output');

Output:

<?xml version="1.0"?>
<main>
   <cust>
       johndoe@gmail.com
   </cust>
<export>
  <config>
    <Exported Name="test">
      <values>
        <node name="yellow"/>
        <node name="green"/>
        <node name="red"/>
      </values>
    </Exported>
  </config>
</export></main>

OTHER TIPS

It seems that SimpleXML does not allow such manipulation. Its easy to replace node content by simple text;

$xml->config->Exported->values = 'Nodes were here.';

But if I try to put XML or SimpleXMLElement using this way, I fail.

$xml->config->Exported->values = '<a>asd</a>';

produces «&lt ; a &gt ;asd &lt ;/a &gt ;». I also tried to call conctructor of SimpleXMLElement to make a node content and insert it into another node.

$xml->config->Exported->values = new SimpleXMLElement…

It inserts just space. So, using SimpleXML only the solution is to scan XML and create a new one.

In my opinion, the most powerfull way to reorganize XML is XSLT.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top