1

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.

  • Something I like about SimpleXML is that instead of `addChild()`, you can also use object notation to set new values `$data->id = $i;` – Nigel Ren Apr 08 '20 at 06:18

1 Answers1

3

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?

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I have followed your instructions, although `` has increased by itself but I have problems ``, `` and `` are on the same line, `` is at the end instead of above `` like this: `1203XXX `. Here is a snapshot of the result: [Resuilt](https://i.imgur.com/k2kuqk9.png) Here is the code: [Code](https://i.imgur.com/dm1So9l.png) – Tư Mã Tần Quảng Apr 08 '20 at 15:33
  • 1
    `SimpleXMLElement` doesn't have a way to add at any place except the end of a node. See https://stackoverflow.com/questions/2092012/simplexml-how-to-prepend-a-child-in-a-node for how you can prepend. – Barmar Apr 08 '20 at 16:36
  • I did it, using that guide in conjunction with replace. Now I want to move the entire `` up to ``, is there any way? – Tư Mã Tần Quảng Apr 09 '20 at 16:56
  • I'm not sure what you mean by that, isn't that what that question shows how to do? In general, order of tags in an XML node shouldn't matter. – Barmar Apr 09 '20 at 17:34
  • Currently, `` is under ``, I would like to ask is there a way to move the entire `` up above ``? Because it is located at the end, the observation is quite difficult. – Tư Mã Tần Quảng Apr 10 '20 at 15:23
  • Isn't that what the other question explains how to do? – Barmar Apr 10 '20 at 16:14
  • I need to create a new question? – Tư Mã Tần Quảng Apr 10 '20 at 16:25
  • If the technique in that question isn't working, you could post a comment there. – Barmar Apr 10 '20 at 16:26