PHP and XML manipulation

Recently I’ve been fiddeling around with an old project of mine, and decided to extend it into a full-blown framework, just for kicks. Born from GDO, a ORM layer for PHP, it’s supposed to serve no real purpose but personal gratification.

Anyway, parallel with the framework I am building a website to showcase it. I also decided that in this specific case all the HTML documents should be built from either PHPs DOM or SimpleXML libraries, I personally dislike having HTML strewn across the project, so I’ve seperated structures like forms and tables into classes and the idea is that I can simply append them to the current page at a specific node and it’ll render the HTML when everything is added.

The problem

Here in lies the problem, PHPs XML libraries (at least the ones that I tried) require you to drag the top node to which you want to append whatever around in all helper classes and such, allow me to demonstrate.

<?php
$document = new DOMDocument();
 
$table = new DOMElement('table');
 
$row = new DOMElement('tr');
$row->appendChild(new DOMElement('td', 'test element'));
 
$table->appendChild($row);
$document->appendChild($table);

One would expect this all to work out fine and produce the following XML document;

<?xml version='1.0' encoding='utf-8' ?>
<table><tr><td>test element</td></tr></table>

In fact, it won’t. It won’t even run. PHP bails out during run time with the error “DOMException: No Modification Allowed Error“. This is because every DOMElement object not created with DOMDocument::createElement() is by default read-only, as you can read in the description of DOMDocument::__construct().

Besides begging the PHP developers to make every DOMElement not read-only on construction, the obvious solution would be to add the DOMElement in question to the DOMDocument and continue building from there, but that’s the problem. It seems counter-intuitive to pass the DOMElement or DOMDocument that you want to append your seperate structure to to every constructor of every XML producing class (or via normal methods of course).

I’ve taken the literal example of PHPs DOM classes, but I’ve tested SimpleXML as well, which provides even less flexibilty regarding node reuse and other fancy stuff one could want to do with XML documents.

Workarounds

There are several solutions to this problem, to name a few:

  • Create a singleton class that holds one instance of DOMDocument, and use a wrapper method somewhere to either get a valid DOMElement
  • Have all classes that produce XML nodes use a fake DOMDocument, and then use DOMDocument::importNode() at the return-point to import the nodes (very inefficient, especially when using a deep-copy).
  • Have the classes that produce XML nodes return nested arrays containing all name -> content relations of the nodes and run through them when it’s sensible to do so.

I’ll leave it as an exercise to the reader to pick out the best method. I haven’t found a solution yet, but I hope to contact the DOM XML module maintainer and discuss this with him/her.

Tags: , ,

One Response to “PHP and XML manipulation”

  1. Hi,

    thanks for your explanation and I pretty much have the same
    conclusions as yourself, the api is just badly put together, we
    should be able to do what you have outlined you expected to work, as
    I also expected that to happen to.

    It seems it’s just another one of PHP’s many flaws and quirks, that
    the programmers who produce the API’s are not professional enough to
    understand how to correctly put together an API that is useful to
    other people, it seems that people just hack together any old
    solution and shovel it into the system, without any regard of
    whether it’s a good idea, or whether it’s fully thought through.

Leave a Reply