Adding a Doctype Declaration to a DOMDocument in PHP
Posted in PHP and Programming on Monday, the 9th of March, 2009.
Tagged: dom, domdocument, dtd, php and xml
I've recently been spending quite a lot of time with PHP's DOM extension, which is extremely useful for both generating and parsing XML.
In this particular case, I'm generating XML, and it's imperative that the XML markup which the code is generating should contain a Doctype declaration (DTD). It isn't hard to do that using DOM, but it did take a little bit of hunting around in the manual and online, so here's a quick overview of how to add a Doctype declaration to a DOMDocument.
Of course, there isn't anything as handy as, say, $document->addDoctype('xhtml')
, that would be too easy. Instead, the first step is to instance DOMImplementation
, and have that create an instance of DOMDocumentType
.
Once the DOMDocumentType
object has been created, it can be passed as a parameter to DOMImplementation::createDocument()
, which returns a DOMDocument
that you can start working with.
That isn't terribly clear, so let's take a look at an example in action. In this case let's imagine that we're generating a WML page, and so our DTD will look like:
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.3//EN" "http://www.wapforum.org/DTD/wml13.dtd">
DOMImplementation::createDocumentType()
takes three parameters: "the qualified name of the document type to create", "the external subset public identifier" and finally "the external subset system identifier". If that means as little to you as it did to me, don't worry: they can all be copied and pasted directly from an existing Doctype declaration. The PHP code is as follows:
<?php $implementation = new DOMImplementation(); $dtd = $implementation->createDocumentType('wml', '-//WAPFORUM//DTD WML 1.1//EN', 'http://www.wapforum.org/DTD/wml_1.1.xml'); $document = $implementation->createDocument('', '', $dtd);
From then on, you can work with $document
exactly as with any other DOMDocument
, for that is what it is.
For good measure, here's an example of creating an XHTML Mobile Profile (XHTML-MP) document:
<?php $implementation = new DOMImplementation(); $dtd = $implementation->createDocumentType('html', '-//WAPFORUM//DTD XHTML Mobile 1.1//EN', 'http://www.openmobilealliance.org/tech/DTD/xhtml-mobile11.dtd'); $document = $implementation->createDocument('', '', $dtd);
Once this is all in place, the Doctype declaration will automatically be added to the WML or XHTML generated by, for example, DOMDocument::saveXml()
.
Validation
One really nice side effect of specifying the DTD in a DOMDocument is that the document itself can subsequently be validated against the DTD very easily. It's as simple as:
<?php $document->validate();
That's a nice win, and a helpful addition to your test suite if you happen to be unit testing code which generates markup - which can otherwise be very fiddly indeed. DOMDocument::validate()
returns a boolean true/false, so it should be trivial to integrate this into tests written against any testing framework.
Posted by José on Friday, the 6th of November, 2009.
Hi, and thanks for its post, really help me so much to made something like that, but i have a doubt. How can insert a DocType to a DOMDocument that i already load from a XML file whit $domdocument->load('my.xml')?
Its file have not a doctype declared, but for make a validation i need insert it.
Can you give me some idea?