PHPLibs has an HTML module which contains the HTMLTag and HTMLDoc class. Those two classes have many commons with DOM’s element and document specification, but they are actually complete different and dont try to use it for DOM parsing and manipulation.

PHPLib’s html module was designed to generate html source and not parse one. It is the opposite of php’s native DOM usage, where most of the times is used to parse xhtml/html source. This is because creating elements using the DOM specification could be very painfull and you will probably loose hours of writing while you could just dump static html code or generate dynamic code using a home-made string concatenation function like “my_html_tag”.

The birth of HTML module

$dom = new DOMDocument('1.0', 'iso-8859-1');
$element = $dom->appendChild(new DOMElement('root'));
$element_ns = new DOMElement('pr:node1', 'thisvalue', 'http://xyz');
$element->appendChild($element_ns);
echo $dom->saveXML(); /* <?xml version="1.0" encoding="iso-8859-1"?>
<root><pr:node1 xmlns:pr="http://xyz">thisvalue</pr:node1></root> */

Imagine using the above format to create numerous nested elements… like nightmare. The first time I wanted to create dynamic html I realized that there were only two ways for me, either template engine or string crafting in source. However we know very well that as web is evolving we are heading towards micro-formats and CSS for styling, and using template engines nowadays is like using rock to cut a potato.

So for me the only was to start echo this and concat that to create html code. Instantly, the door bell rings and some old friends came to visit me. Mr. Mess, Mrs Insecurity with their ugly kids which I still haven’t learned their names. I realized that this is dead-end for me, I slammed the door and started thinking how on heck can I have simple dynamic html, in a secure, easy, portable, html version independant and fast way to use.

This was the start of HTMLTag, which is still missing many many things, but it is usable, safe and quite fast. Lets see how can this module help us to ease our path to successful programming. HTMLTag has almost the same usage like DOMElement, you have to create it by instantiating the class and append it to parent element, so to create a 2×2 table you have to do something like this:

// A 2x2 table creation
 $table = new HTMLTag('table',
     new HTMLTag('tr',
         new HTMLTag('td', 'row 1 col 1'),
         new HTMLTag('td', 'row 1 col 2')
     ),
     new HTMLTag('tr',
         new HTMLTag('td', 'row 2 col 1'),
         new HTMLTag('td', 'row 2 col 2')
     )
 );

You will start thinking that I am idiot to create something that has the same disadvantages of what I am whining for. Well object instantiation process is not the best and there are some plans to improve it, but there is a faster way to do the same by using shortcut functions like tag().

// A 2x2 table using tag() shortcut
 $table = tag('table,
     tag('tr',
         tag('td', 'row 1 col 1'),
         tag('td', 'row 1 col 2')
     ),
     tag('tr',
         tag('td', 'row 2 col 1'),
         tag('td', 'row 2 col 2')
     )
 );

The above example showed how to created nested tags. It was done in the same and less number of characters that you would need to write html, so we are on the right direction. Apart from this, all the data are implicitly escaped preventing any script injections techniques or unwanted disformation of the output. There is off course an easy way to explicitly inject html code.

Show me some magic

You are probably expecting to see a miracle or something, but you will not find one here. However there are some tricks that should be mentioned. In the next paragraphs I will show you what HTMLTag is capable to do at the moment and how it can help you in development.

Automatic rendering

HTMLTag supports automatic rendering of tags by casting them to strings. When php demands the string format of the object it will render itself and all childs and return the html code.

Continuing with the above example, the following code will echo the html.

echo $table; // $table will call render() automatically and return html code

There is also another shortcut function named etag() which is a shortcut of “echo tag()” so if you wanted to create the table and sent it to output buffer you could do:

etag('table,
     tag('tr',
         tag('td', 'row 1 col 1'),
         tag('td', 'row 1 col 2')
     ),
     tag('tr',
         tag('td', 'row 2 col 1'),
         tag('td', 'row 2 col 2')
     )
 );

Render in HTML or XHTML

HTMLTag is capable to render HTML and XHTML compliant code depending on what it will be asked to do. Rendering mode can be controlled globally or per tag. By default HTMLTag renders in html mode, this can be changed by changing the static property $default_render_mode to “xhtml”.

So if you wanted to render table in xhtml it can be done like this

HTMLTag::$default_render_mode = 'xhtml';
echo $table;

You will probably decide your rendering mode in one place and this must be done before any rendering occurs. You could even use different output modes depending on the agent that client is using.

Note that HTMLDoc is also checking HTMLTag::$default_render_mode for selecting document type.

Automatic appending – looking for better name -

HTMLTag supports a way to automatic append new tags without explicit telling them to append to a parent. This is controlled through a stack where you can push and pop parents and by using etag the tag is appended in the last pushed parent. The concept and api are simple, but can help a lot when creating dynamic number of elements.

So let’s see how can this be help full when creating a table of something

tag('table')-&gt;push_parent(); // This make tag table the active parent

foreach($products as $product)
{   etag('tr')-&gt;push_parent();  // We use etag to append it to current
                                // parent and then push this to make it active parent
    etag('td', $product-&gt;id);
    etag('td', $product-&gt;name);
    etag('td', $product-&gt;price);
    HTMLTag::pop_parent();      // Pop tr parent
}
echo HTMLTag::pop_parent();  // Pop table and echo it

This can be very helpful when creating nested formats, permitting to change parent or child structure without need to rewrite code of the affected ones. The source is also much cleaner and smaller than moving around variables and using append() for each tag.

I have a dream…

HTMLTag is more useful for me than the other solutions, but it is not what I really want and there is a lot of work before it is complete. What I am still missing is DOM features, although HTMLTag is DOM-like it misses all the good stuff like XPath etc. There is also a project named phpquery which can work on DOM trees to select nodes using CSS3 rules, very much like jQuery, this however can’t work with HTMLTag unless it is converted to really DOMElement objects.

There are also sometimes that you want pure static html but it needs to interact with dynamic html like appending it to a object. The only way to do it is by creating static html using HTMLTag objects element by element, and this is an overkill. There should be a way to parse small chunks of html or even complete documents, like DOM does.

What I am thinking is make HTMLTag a wrapper arround DOMElement so that can have all features of HTMLTag and all features of DOMElement. This can be improved by implementing a way for even simpler dynamic object creation something like

$.TABLE(
     $.TR(
         $.TD('row 1 col 1'),
         $.TD(td', 'row 1 col 2')
     ),
     $.TR(
         $.TD('row 2 col 1'),
         $.TD('row 2 col 2')
     )
 );

I am dreaming for HTML module that is a complete output device, injecting data directly from output buffer to html elements, or even directly parsing output buffer and creating trees. Searching replacing and modifying should be really trivial.