Recomposer un HTML valide après l'avoir tronqué.

Récemment, je me suis occupé de la création d'un site web tout joli tout beau, dans lequel les webmasters peuvent composer certaines parties de leur site web via un éditeur online wysiwyg. Mais à certains endroits, j'avais besoin de mettre juste le début du texte suivi des traditionnels 3 petits points.

Même si cet éditeur génère un code (x)html tout à fait valide, le fait de couper la chaîne peut rendre complètement invalide le code général de la page. Pour vous donner un exemple, je peux vous montrer ce que j'avais :

<p><span style="color: blue;">Bienvenue dans ce nouveau dossier</span></p>

Si je décide de tronquer à 45 caractères, et que je rajoute les « ... », et que je ferme ma balise <p>, j'obtient :

<p><span style="color: blue;">Bienvenue dans...</p>

Et il me manque la fermeture de mon span. Heureusement les navigateurs « comprennent » l'erreur et la corrige. Ils ferment donc la balise et continuent d'afficher à peu près correctement le reste de l'(x)html. Seulement le validateur du W3 n'est pas aussi clément. Je suis donc allé chercher quelques solutions afin de pouvoir fermer automatiquement toutes les balises ouvertes qui sont à fermer. Je suis entre autre tombé sur http://codesnippets.joyent.com/posts/show/959, une solution à base de preg. Ce code a été repris sur ce site. Cette deuxième adresse est plus intéressante car, dans un commentaire, il y a une fontion qui gère les balises qui s'auto ferment ( comme <br />, <hr /> ou <img src="" />). Mais ces solutions à base de PHP pure ne m'ont pas assez satisfait. Il faut dire que le PHP-PCRE n'est pas un modèle de rapidité.

J'ai continué mes recherches, et je suis tombé sur un forum VB (aïe pataper) qui parle de PHP (l'honneur est sauf). En gros une des réponses c'est de regarder du coté des objets DOM de PHP. C'est une solution très intéressante car elle est built-in dans PHP,et est donc plus rapide (enfin normalement) que du code PHP.

J'ai notamment parcouru les possibilités de DOMDocument::loadXML et DOMDocument::loadHTML. Cette deuxième méthode à l'avantage de corriger les erreurs de syntaxe :

Description bool DOMDocument::loadHTML ( string $source )

Cette fonction analyse un document HTML contenu dans la chaîne source . Contrairement au XML, le HTML n'a pas besoin d'être bien formé pour être chargé. Cette fonction peut aussi être appelée statiquement pour charger et créer un objet DOMDocument. L'appel statique peut être utilisé lorsque vous n'avez besoin de configurer aucune propriété de DOMDocument avant le chargement.

Voilà qui est intéressant. Il s'en suivi quelques tests. Il s'est avéré que DOMDocument::loadXML permet de charger un code html non valide, et de le ressortir valide avec DOMDocument::loadHTML. Par contre cette méthode retourne le code HTML complet, Doctype et balises <html><body> compris. Rien de bien grave en soi.

Voici donc ma solution permettant de ravoir un code html valide :

function validateHtml($pString) {
        $dom = new DOMDocument;
        // chargement du code html
        $dom->loadHTML($pString);
        // html valide
        $txt = $dom->saveHTML();
        // traitement du fichier. On va d'abord séparer les lignes
        $txt = explode("\n", $txt);
        // suppression du doctype
        array_shift($txt);
        // on garde le reste
        $txt = $txt[0];
        //on enlève les balises d'ouverture et de fermeture du code html pour ne garder que  le corps
        $txt = str_replace(array('<html><body>', '</body></html>'), '', $txt);
        return $txt;
}

Haut de page