Before going deeper, is a save of the sorted state really necessary? Like in a database, you can always sort items when retrieving them, same here with the code you have already written.
That said, "updating" in your case means delete all <image>
nodes and add them back in order.
Update:
see fusion3k's answer, that it is not necessary to delete nodes, but just append them. I'd suggest to go with his solution.
You are using SimpleXml
, which does not provide methods for copying nodes. You will need to re-create every single node, child-node, attribute.
Your XML looks simple, but I guess it is an example and your real XML is more complex. Then rather use DOM
and its importNode()
method, which can copy complex nodes, including all their attributes and children.
On the other hand, SimpleXml
to me feels much easier, so I combine both:
$xml = simplexml_load_string($x); // assume XML in $x
$images = $xml->xpath("/stuff/images/image");
usort($images, function ($a, $b){
return strnatcmp($a->sorted_number, $b->sorted_number);
});
Comments:
xpath()
is a quick way to get all items into an array of SimpleXml
objects.
$images
is sorted now, but we can't delete the original nodes, because $images
holds references to these nodes.
This is why we need to save $images
to a new, temporary document.
$tmp = new DOMDocument('1.0', 'utf-8');
$tmp->loadXML("<images />");
// add image to $tmp, then delete it from $xml
foreach($images as $image) {
$node = dom_import_simplexml($image); // make DOM from SimpleXml
$node = $tmp->importNode($node, TRUE); // import and append in $tmp
$tmp->getElementsByTagName("images")->item(0)->appendChild($node);
unset($image[0]); // delete image from $xml
}
Comments:
- using
DOM
now, because I can copy nodes with importNode()
- at this point,
$tmp
has all the <image>
nodes in the desired order, $xml
has none.
To copy nodes back from $tmp
to $xml
, we need to import $xml
into DOM
:
$xml = dom_import_simplexml($xml)->ownerDocument;
foreach($tmp->getElementsByTagName('image') as $image) {
$node = $xml->importNode($image, TRUE);
$xml->getElementsByTagName("images")->item(0)->appendChild($node);
}
// output...
echo $xml->saveXML();
see it in action: https://eval.in/535800