Add nodes to SimpleXMLElement
“You know, it’s at times like this, when I’m trapped in a Vogon airlock with a man from Betelgeuse, and about to die of asphyxiation in deep space, that I really wish I’d listened to what my mother told me when I was young.”
“Why, what did she tell you?”
“I don’t know, I didn’t listen.”—Ford Prefect and Arthur Dent (The Hitchhiker’s Guide to the Galaxy)
One of the things I tell our developers is that when a solution starts becoming unbearably complex you’re probably looking at it the wrong way. An obvious example from just this week is that it’s difficult if not impossible to automatically style a border to the right of every element in a list except for the last one, but it’s very easy to style a border to the left of every element except for the first one.
I should listen to myself more often. I just spent far too much time trying to figure out how to create a new node in PHP’s SimpleXML and add it as a child to an existing node.
I have a simple array that I want to serialize into somewhat future-proofed, readable text for storage in a database. XML seemed like the obvious solution. The array contains a dictionary-like list of fields and values. Some of those values can be arrays themselves, but those will be simple one-dimensional lists, and none of the array values will themselves be arrays—the rabbit hole only goes two deep at most.
Adding the non-arrays was easy using SimpleXMLElement::addChild. Creating a list of elements was easy enough, too, creating a new SimpleXMLElement and adding items to it. But adding that list to the parent seemed impossible.
[toggle code]
-
function arrayToXML($myArray) {
- $arrayXML = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><fields />');
-
foreach ($myArray as $field=>$value) {
-
if (is_array($value)) {
- //this is a list, and needs to have several items
- $list = new SimpleXMLElement("<$field />");
-
foreach ($value as $item) {
- $list->addChild('item', $item);
- }
- //there is no such function by any name in SimpleXML
- $arrayXML->appendChild($list);
-
} else {
- //scalar, so just add it directly
- $arrayXML->addChild($field, $value);
- }
-
if (is_array($value)) {
- }
- return $arrayXML->asXML();
- }
First I looked all over for a built-in method to add an existing node to a parent element; all I could find was people overriding SimpleXMLElement in complex ways. Then I discovered that SimpleXMLElements can be accessed simultaneously as DOM elements—but discovered that nodes can’t be added to orphan nodes.
There was no way that something called “SimpleXML” could be so complex for such obvious functionality.
I had just about given up when I noticed some pale green text I’d missed: addChild, which was working fine for me, returned a SimpleXMLElement. The correct solution was not to create a child and add it to the parent. The correct solution is to add the child to the parent, and then create it.
[toggle code]
-
function arrayToXML($myArray) {
- $arrayXML = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><fields />');
-
foreach ($myArray as $field=>$value) {
-
if (is_array($value)) {
- //this is a list, and needs to have several items
- //so first add the child
- $list = $arrayXML->addChild($field);
- //and then populate the child
-
foreach ($value as $item) {
- $list->addChild('item', $item);
- }
-
} else {
- //scalar, so just add it directly
- $arrayXML->addChild($field, $value);
- }
-
if (is_array($value)) {
- }
- return $arrayXML->asXML();
- }
Duh.
- SimpleXML
- “The SimpleXML extension provides a very simple and easily usable toolset to convert XML to an object that can be processed with normal property selectors and array iterators.”
More PHP
- Web display of Taskpaper file
- It is easy to use PHP to convert a Taskpaper task file into simple HTML conducive to styling via CSS.
- New PHP Tutorial
- I’ve just uploaded a new version of my PHP tutorial, with a better MySQL section.
- MySQL for other applications
- I’ve just uploaded a MySQL tutorial that focuses on using MySQL in programs such as Dreamweaver. It goes over importing data, viewing data, and updating data.
- Webmaster in a Nutshell
- Without doubt the best reference work for webmasters that you’ll find. It contains the “reference” part of most of O’Reilly’s web-relevant nutshell books. You can find references for HTML 3.2, the CGI standard, JavaScript, Cascading Style Sheets, PHP, the HTTP 1.1 protocol, and configuration statements and server-side includes for the Apache/NCSA webservers.
More Duh
- Django using too much memory? Turn off DEBUG=True!
- DEBUG=False can save hundreds of megabytes in Django command-line scripts, and probably in Django web processes.
- No distutils? Install Xcode
- If Distutils is not available on Mac OS X Leopard, install the Xcode developer tools. Also, the upgrade process I followed for upgrading from Mailman 2.1.9 to 2.1.12.
- Django QuerySet Heisenberg gotcha
- Observing a system changes the system. That’s especially true with Django’s QuerySet API.
More XML
- A present for Palm
- Palm needs a little help understanding XML.
- Automatically distributing images within XHTML
- One of the nice things about XHTML is that the tools for reading XML have finally matured. So if, for example, I want to have a series of images automatically placed within my web page, I can parse the XHTML of the content to ensure that nothing is broken.
- Django Twitter tag and RSS object
- I wanted to embed my twitter feed into my Django blog, and didn’t see any simple RSS readers for Python that did what I wanted.
- Code formatting Django tag
- xml.dom.minidom makes it easy to format code snippets into lists.
- Excerpting partial XHTML using minidom
- You can use xml.dom.minidom to parse partial XHTML as long as you use a few tricks and don’t mind that getElementById doesn’t work.

October 31, 2009: I updated the base SimpleXMLElement to be UTF-8; without the “<?xml version="1.0" encoding="UTF-8"?>” declaration, it defaults to whatever happens to be the default in the PHP you’re using, which isn’t necessarily going to match what the database this will be stored in is using, nor what the web page this appears in is using.