0

So this might seem like a dumb question, but I can not find a single example of it. What I am looking for is a way to update an XML file WITHOUT knowing the names or attributes or anything about the file per say to hard code.

How I intend to do this, is I have php that reads the xml file, and creates a html form with a text field for each name + attribue combo ex:

<Tools>
        <RangeScrew Red="255" Green="192" Blue="203"/>
        <RangeRing Red="255" Green="192" Blue="203"/>
</Tools>

If it loaded something like this, it would look something like this:

Example generated HTML

So from here say I changed one of the values and clicked update value, I can pass any info to the next function, such as the name of the attribute, the node of the xml tree, or the whole node/parent combo. Since it will be heavily nested XML files.

There is a ton of examples where people hard code the path to these nodes to update them but I can't find a dynamic way. Any suggestions if I wanted to update? lets say if the example I gave was nested several deep.

Lain
  • 2,166
  • 4
  • 23
  • 47
  • "What I am looking for is a way to update an XML file WITHOUT knowing the names or attributes or anything about the file per say to hard code." Sounds like complex it also means programming A.I to get that one... Besides you know XML stands for Extensible Markup Language right? How would you program something without using fixed rules to parse information from something which is **extensible**.. – Raymond Nijland Feb 02 '19 at 16:35
  • Get all form datas and rebuild xml from. What you can't ? – splash58 Feb 02 '19 at 16:38
  • @RaymondNijland I think it isn't that complex, since I know the parent node path/names and the attribute names, it just needs some way to read in the XML, recursively search it for whatever path, then update that node/attribute. Then save the XML. Don't think AI is needed – Lain Feb 02 '19 at 16:45
  • Ok maybe A.I was the incorrect word to use you need a smart algoritme to do it which can be "complex" to write.. Otherwise you would have found a example already.. – Raymond Nijland Feb 02 '19 at 16:47
  • Which is why I went to stack overflow, doesn't need to be exact code, just concept of how to do it. I feel I can't be the only one with this problem, so would be good for future people too. – Lain Feb 02 '19 at 16:57
  • I might be off base here but I think you could load the file into an object with simplexml_load_file. When your form is submitted update the values on the object. Then save object to xml using PEAR's XML_Serializer package. – beenhere4hours Feb 02 '19 at 17:10
  • 1
    [SimpleXML API](http://php.net/manual/en/book.simplexml.php) will not work @dmasi if does not have methods to update or delete annything in a existing XML document it can only add.. The topicstarter needs to look into [DOMDocument API](http://php.net/manual/en/class.domdocument.php) – Raymond Nijland Feb 02 '19 at 17:15
  • @RaymondNijland agreed that's a better solution. I was thinking they would have to write a custom method to update the underlying object. – beenhere4hours Feb 02 '19 at 17:28
  • 1
    @RaymondNijland - [update a node using SimpleXML](https://stackoverflow.com/questions/32111703/change-value-of-current-child-simplexml-php) or [delete in SimpleXML](https://stackoverflow.com/questions/262351/remove-a-child-with-a-specific-attribute-in-simplexml-for-php) – Nigel Ren Feb 02 '19 at 21:22
  • Yes the "delete in SimpleXML" happens as a DomDocument object @NigelRen (atleast the accepted answer does it like that) – Raymond Nijland Feb 02 '19 at 21:42
  • @RaymondNijland as the answer says (not the accepted answer though) `unset($xml –> a –> b –> c);` – Nigel Ren Feb 02 '19 at 21:44
  • Well @NigelRen i would trust the update for childs and attributes method (the object setting method) because that one is officially mentioned in the PHP [manual}(http://php.net/manual/en/function.unset.php) (as example 9 it seams).. The `unset()` method to delete childs/attributes it's not officially mentioned in the manual but it seams to be working.. But if `unset()` works in thoery the (unset) cast like `(unset) $child[0];` and NULL setting like `$child[0] = NULL;` should also work to delete items.. I used DomDocument more for XML data. – Raymond Nijland Feb 02 '19 at 22:04
  • 1
    @RaymondNijland DOMDocument is great for detailed control (inserting elements n specific positions etc.) SimpleXML is quite crude - but Simple and assumes a certain amount of 'magic' methods working to get at data. – Nigel Ren Feb 02 '19 at 22:08
  • Very true @NigelRen.. Topicstarter and future readers be sure security wise to use `libxml_disable_entity_loader(true);` before working with anny PHP XML parsers (SimpleXML and DomDocument and others for that matter) to prevent [XML External Entity attacks](https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing) in your PHP website/application especially if the XML is controlled by user input or send from the outside (with AJAX for example). – Raymond Nijland Feb 02 '19 at 22:13

1 Answers1

0

A very simple example of what you can do with SimpleXML and updating an element in any position.

So if you wanted to update the value of the Blue attribute of <RangeScrew>, you can store a path of /Tools/RangeScrew/@Blue, which defines where it is in the hierarchy with @ to denote an attribute (this also happens to be an XPath expression). You can then use this to locate the value to update.

$source = '<Tools>
        <RangeScrew Red="255" Green="192" Blue="203"/>
        <RangeRing Red="255" Green="192" Blue="203"/>
</Tools>';

$path = "/Tools/RangeScrew/@Blue";
$value = "10";

$xml = simplexml_load_string($source);

// xpath returns a list of matches, so use [0] to get the first entry
$element = $xml->xpath($path)[0];
// Update the value (using [0] calls the magic method which allows you to set
// the value
$element[0] = $value;

echo $xml->asXML();

So this sets the Blue attribute to 10 and outputs the resultant XML...

<?xml version="1.0"?>
<Tools>
        <RangeScrew Red="255" Green="192" Blue="10"/>
        <RangeRing Red="255" Green="192" Blue="203"/>
</Tools>
Nigel Ren
  • 56,122
  • 11
  • 43
  • 55