Search code examples
phpxmlsimplexml

PHP SimpleXMLElement addChild in a loop only show once with largest value


I have an XML file:

<include>
    <data>
        <name>Chicken</name>
        <price>1</price>
    </data>
    <data>
        <name>Fish</name>
        <price>5</price>
    </data>
    ...Cut off about 100 lines...
    <data>
        <name>Pig</name>
        <price>105</price>
    </data>
<include>

Now, I want to add the ascending <id>, right above the <name> like this:

<include>
    <data>
        <id>1203001</id>
        <name>Chicken</name>
        <price>1</price>
    </data>
    <data>
        <id>1203002</id>
        <name>Fish</name>
        <price>5</price>
    </data>
    ...Cut off about 100 lines...
    <data>
        <id>1203105</id>
        <name>Pig</name>
        <price>105</price>
    </data>
<include>

I used the for loop, here is my code:

$data = <<<XML
<include>
    <data>
        <name>Chicken</name>
        <price>1</price>
    </data>
    <data>
        <name>Fish</name>
        <price>5</price>
    </data>
    ...Cut off about 100 lines...
    <data>
        <name>Pig</name>
        <price>105</price>
    </data>
<include>
XML;
for($i = 1203001; $i <= 1203105; $i++) {
    $xml = new SimpleXMLElement($data);
    $xml->data->addChild("id", $i);
}
echo $xml->asXML();

However, the result I get is that <id> only appears once, with the largest value, next to </data> instead of the position I want::

<include>
    <data>
        <name>Chicken</name>
        <price>1</price>
    <id>1203105</id></data>
    <data>
        <name>Fish</name>
        <price>5</price>
    </data>
    ...

Please show me a method to solve this problem. I would appreciate your solution.


Solution

  • You're recreating $xml from $data every time through the loop, so you're discarding the changes you made on the previous iteration.

    Initialize $xml before the loop. Then loop over the data child nodes.

    $xml = new SimpleXMLElement($data);
    $i = 1203001;
    foreach ($xml->data as $node) {
        $node->addChild("id", $i++);
    }
    

    If you want to insert <id> at the beginning of the <data> node instead of the end, see SimpleXML how to prepend a child in a node?