Indeed the generated HTML is broken. More details for differences
between XHTML and HTML:
http://www.w3.org/TR/xhtml1/diffs.html and
http://www.w3.org/TR/xhtml1/guidelines.html
And more in depth:
http://www.cs.tut.fi/~jkorpela/html/empty.html
In particular, the problem is generating "minimized" elements, such as
<br />. In HTML (which is a dialect of SGML and has little to do with
XHTML or XML), the slash in this context is a null end tag, which can be
used as a shorthand for closing tags. Thus, <br /> translated to the
more ordinary form is <br>>, i.e. line break followed by greater than.
Naturally this breaks validators.
In HTML::Tiny, these elements are called "closed" elements.
Apparently Andy Armstrong has already anticipated this, because there
are two places in the source code marked with a comment indicating than
a special "xml mode" flag is needed. A patch is attached, which lets the
user give a parameter to the constructor. By default, the module
generates XHTML. Use the following to make it generate valid[1] HTML:
my $h = HTML::Tiny->new(mode => 'html');
The patch is otherwise trivial, except that all n+1 tests needed to be
updated as well. As a bonus the patched version now generates correct
empty attributes; i.e. <input checked="checked" /> instead of <input
checked />.
[1] Valid as defined "do what I intend, not what I ask for".