Respect / Template

Experimental, HTML-only templating engine
Other
38 stars 6 forks source link

Define Doctype in render time #20

Closed augustohp closed 10 years ago

augustohp commented 12 years ago

We should be able to pass as an argument to render() the Doctype we want the HTML.

nickl- commented 12 years ago

See proposed fix @ Respect/Template#24 not sure if this is what you had in mind.

This is the only way I can think of to add the doctype at render otherwise we need to do it on create via the DOMImplementation by first retrieving a DTD through the complex createDocumentType method which requires 3 separate parameters for the doctype ([ string $qualifiedName = NULL [, string $publicId = NULL [, string $systemId = NULL ]]] ) before eventually creating a DOMDocument via createDocument by passing the DTD (3rd parameter).

What a ball ache!

Here is an example: http://pointbeing.net/weblog/2009/03/adding-a-doctype-declaration-to-a-domdocument-in-php.html

nickl- commented 12 years ago

Ok so I stand corrected, as it turns out I managed to find a way to replace the doctype on render while still being able to pass the actual <!DOCTYPE tag for processing.

By creating a new DOMDocument and via loadHTML($doctype) parsing the DocType tag you are able to access it as a DOMNode or more specifically a DOMDocumentType. Although the current DOMDocument would have nothing to do with this doctype, neither clone, cloneNode, importNode, nada! It does however allow us to simply replaceChild when using a doctype created from a DOMImplementation instance and since we can retrieve the properties from the newly created doctype to pass as parameters we can stick with the simple solution of supplying the <!DOCTYPE tag instead of $doctype_name, $doctype_public_id and $doctype_system_id which I've never heard of before today but there you have it:

<?php

    if ($doctype) {
            $doc = new DOMDocument();
            $doc->loadHTML($doctype);
            $dt = $doc->doctype;
            $di = new DOMImplementation();
            $dt = $di->createDocumentType($dt->name, $dt->publicId, $dt->systemId);
            $this->dom->replaceChild($dt, $this->dom->doctype);
    }

    return preg_replace('/<\?xml[\s\S]*\?>\n/', '', $this->dom->saveXML());

Trying to return saveHTML() after this hop skip and jump confuses the poor soul to no ends and these are only some of the garbage you can expect to find:

<!DOCTYPE DOMDocument>
<!DOCTYPE html PUBLIC "" "">
<!DOCTYPE Trying PUBLIC "to get property" "of non-object">
<!DOCTYPE /Respect/Template/library//Respect/Template>

But saveXML() returns the information as expected and at least preg_replace of the xml declaration won't leave you up at nights worrying if the regex will only consider the tokens between <? to ?> way much easier would you agree?

The xml declaration we trim before consumption:

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>

The new solution was also committed and is available at Respect/Template#24, you can now pick and choose from 2 options.

Enjoy! =)

I can't thank you guys enough for these awesome libraries, they make me all warm and fuzzy inside.

alganet commented 12 years ago

I wonder what happens if we do $dom->saveXML($dom->documentElement);. By the docs, it should output any node without the XML declaration. Perhaps the DOMDocumentType gets printed as well.

nickl- commented 12 years ago

SaveXML alwaysl adds the xml declaration but is happy with the DOCTYPE change given it was perfect XHTML or loaded wit loadHTML. saveHTML on the other hand chokes and totally scrambles the html after a doctype replace hence the use of saveXML.

Aren't we sick of this already, I know simple_html_dom is not perfect but it sure beats having to hassle with this stuff over and over... huff.

This us probably obsolete by now as the new DOM whatever it is will have an impact. Lets rather focus on that and we can work this back..

augustohp commented 10 years ago

I consider this fixed with merge of #24

nickl- commented 10 years ago

Not worth the hassles I tend to agree. =)