0

Given a base $xml and a file containing a <something> tag with attributes, children and children of its children, I would like to append it as first child and all of its children as raw XML.

Original XML:

<root>
    <people>
        <person>
            <name>John Doe</name>
            <age>47</age>
        </person>
        <person>
            <name>James Johnson</name>
            <age>13</age>
        </person>
    </people>
</root>

XML in file:

<something someval="x" otherthing="y">
    <child attr="val"  ..> { some children and values ... }</child>
    <child attr="val2" ..> { some children and values ... }</child>
            ...
</something>

Result XML:

<root>
    <something someval="x" otherthing="y">
        <child attr="val"  ..> { some children and values ... }</child>
        <child attr="val2" ..> { some children and values ... }</child>
            ...
    </something>
    <people>
        <person>
            <name>John Doe</name>
            <age>47</age>
        </person>
        <person>
            <name>James Johnson</name>
            <age>13</age>
        </person>
    </people>
</root>

This tag would contain several children both direct and recursively, so it would not be practical to build the XML via the SimpleXML operations. Besides, keeping it in a file would result in lower maintenance costs.

Technically it would simply be prepending one child. The problem is that this child would have other children and so on.

On the PHP addChild page there's a comment that says:

$x = new SimpleXMLElement('<root name="toplevel"></root>');
$f1 = new SimpleXMLElement('<child pos="1">alpha</child>');

$x->{$f1->getName()} = $f1; // adds $f1 to $x

However, this does not seem to treat my XML as raw XML therefore causing &lt; and &gt; escaped tags to appear. Several warnings concerning namespaces seem to appear as well.

I suppose I could do a quick replace of such tags but I am not sure whether it could cause future problems and it certainly does not feel right.

Manually hacking the XML is not an option and neither is adding children one by one. Choosing a different library could be.

Any clues on how to get this working?

Thanks!

wtf8_decode
  • 452
  • 6
  • 19
  • possible duplicate of [SimpleXML how to prepend a child in a node?](http://stackoverflow.com/questions/2092012/simplexml-how-to-prepend-a-child-in-a-node) – Forien Jan 05 '15 at 13:05
  • My main problem is actually adding the raw XML, not the order where the code is added although it would be very desirable for the tag to be on top. The referenced question does not deal with such issue. I just edited my question title to reflect such difference. – wtf8_decode Jan 05 '15 at 13:07
  • I just edited my question to reflect the real issue. – wtf8_decode Jan 05 '15 at 13:18

1 Answers1

0

I'm really not sure if that will work. Try this or downvote this, but I hope it helps. Using DOMDocument (Reference)

<?php
$xml = new DOMDocument();
$xml->loadHTML($yourOriginalXML);
$newNode = DOMDocument::createElement($someXMLtoPrepend);
$nodeRoot = $xml->getElementsByTagName('root')->item(0);
$nodeOriginal = $xml->getElementsByTagName('people')->item(0);
$nodeRoot->insertBefore($newNode,$nodeOriginal);

$finalXmlAsString = $xml->saveXML();
?>

Sometimes UTF-8 can make problems, then try this:

<?php
$xml = new DOMDocument();
$xml->loadHTML(mb_convert_encoding($yourOriginalXML, 'HTML-ENTITIES', 'UTF-8'));
$newNode = DOMDocument::createElement(mb_convert_encoding($someXMLtoPrepend, 'HTML-ENTITIES', 'UTF-8'));
$nodeRoot = $xml->getElementsByTagName('root')->item(0);
$nodeOriginal = $xml->getElementsByTagName('people')->item(0);
$nodeRoot->insertBefore($newNode,$nodeOriginal);

$finalXmlAsString = $xml->saveXML();
?>
Forien
  • 2,712
  • 2
  • 13
  • 30
  • I edited your third line to : `$newNode = $xml->createElement($someXMLtoPrepend);` but I am getting `PHP Fatal error: Uncaught exception 'DOMException' with message 'Invalid Character Error'` and several warnings related to namespaces. The XML is valid and not manually generated. – wtf8_decode Jan 05 '15 at 13:28
  • Are you sure this isn't a case: http://stackoverflow.com/questions/8524111/php-invalid-character-error ? I mean - none of your nodes name starts with number or something? – Forien Jan 05 '15 at 13:31
  • I don't have any tags with a digit at the beginning of their names. I'll look into it anyways. – wtf8_decode Jan 05 '15 at 13:34
  • @wtf8_decode I've added edit to answer, **maybe** it's this, but I'm really not sure. I only used `DOMDocument` with HTML, never with XML, there should be no big difference tho.. – Forien Jan 05 '15 at 13:37
  • Still the same. My XML is not manually generated and even contains `<![CDATA[` tags. I see DOMDocument is getting somewhat confused by it as it still tries to parse the inner XML. The problematic line appears to be the `mb_convert_encoding` one. – wtf8_decode Jan 05 '15 at 13:43
  • I just removed my `CDATA` tag and still the same. I'll keep the XML to a minimum and retry! – wtf8_decode Jan 05 '15 at 13:44
  • I just tried keeping it to the simplest and still getting the same error.`PHP Fatal error: Uncaught exception 'DOMException' with message 'Invalid Character Error' in ... Stack trace: DOMDocument->createElement('?')` – wtf8_decode Jan 05 '15 at 13:45
  • @wtf8_decode XML files need to start with `` line. (and linebreak after it). Otherwise it's not correct nor valid XML file. – Forien Jan 05 '15 at 13:46
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/68222/discussion-between-wtf8-decode-and-forien). – wtf8_decode Jan 05 '15 at 13:48