<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>hatsuseno&#039;s blog &#187; SimpleXML</title>
	<atom:link href="http://blog.hatsuseno.org/index.php/tag/simplexml/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.hatsuseno.org</link>
	<description>rantings on tech</description>
	<lastBuildDate>Tue, 03 Aug 2010 12:58:51 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PHP and XML manipulation</title>
		<link>http://blog.hatsuseno.org/index.php/php-and-xml-manipulation/</link>
		<comments>http://blog.hatsuseno.org/index.php/php-and-xml-manipulation/#comments</comments>
		<pubDate>Thu, 28 May 2009 23:19:30 +0000</pubDate>
		<dc:creator>hatsuseno</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[SimpleXML]]></category>

		<guid isPermaLink="false">http://blog.hatsuseno.org/?p=32</guid>
		<description><![CDATA[Recently I&#8217;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&#8217;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 [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I&#8217;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 <acronym title='Generic Database Object'>GDO</acronym>, a <acronym title='Object-relational mapping'>ORM</acronym> layer for PHP, it&#8217;s supposed to serve no real purpose but personal gratification.</p>
<p>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&#8217;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&#8217;ll render the HTML when everything is added. </p>
<h3>The problem</h3>
<p>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.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$document</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DOMDocument<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$table</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DOMElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DOMElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tr'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$row</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">appendChild</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> DOMElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'td'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'test element'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$table</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">appendChild</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$document</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">appendChild</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$table</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

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

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">'1.0'</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">'utf-8'</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;table<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;tr<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;td<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>test element<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/td<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/tr<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/table<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>In fact, it won&#8217;t. It won&#8217;t even run. PHP bails out during run time with the error &#8220;<code>DOMException: No Modification Allowed Error</code>&#8220;. This is because every <code>DOMElement</code> object not created with <a href='http://php.net/manual/en/domdocument.createelement.php'><code>DOMDocument::createElement()</code></a> is by default <i>read-only</i>, as you can read in the description of <a href='http://php.net/manual/en/domelement.construct.php'><code>DOMDocument::__construct()</code></a>.</p>
<p>Besides begging the PHP developers to make every <code>DOMElement</code> not read-only on construction, the obvious solution would be to add the <code>DOMElement</code> in question to the <code>DOMDocument</code> and continue building from there, but that&#8217;s the problem. It seems counter-intuitive to pass the <code>DOMElement</code> or <code>DOMDocument</code> that you want to append your seperate structure to to every constructor of every XML producing class (or via normal methods of course).</p>
<p>I&#8217;ve taken the literal example of PHPs DOM classes, but I&#8217;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.</p>
<h3>Workarounds</h3>
<p>There are several solutions to this problem, to name a few:</p>
<ul>
<li>Create a singleton class that holds one instance of <code>DOMDocument</code>, and use a wrapper method somewhere to either get a valid <code>DOMElement</code></li>
<li>Have all classes that produce XML nodes use a fake <code>DOMDocument</code>, and then use <a href='http://php.net/manual/en/domdocument.importnode.php'><code>DOMDocument::importNode()</code></a> at the return-point to import the nodes (very inefficient, especially when using a deep-copy).</li>
<li>Have the classes that produce XML nodes return nested arrays containing all name -> content relations of the nodes and run through them when it&#8217;s sensible to do so.</li>
</ul>
<p>I&#8217;ll leave it as an exercise to the reader to pick out the best method. I haven&#8217;t found a solution yet, but I hope to contact the DOM XML module maintainer and discuss this with him/her.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hatsuseno.org/index.php/php-and-xml-manipulation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
