DOMDocument : ajouter des styles CSS inline à la volée
Bonjour,
J'essaie d'utiliser DOMDocument pour parser une chaine HTML, et ajouter "à la volée" des styles CSS inline, en fonction du nom des balises, des classes ou id des balises.
Je débute avec DOMDocument...
Voici un exemple de code : test.php
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
| <?php
header('Content-type:text/html; charset=UTF-8'); // encodage UTF-8
error_reporting(E_ALL); // en TEST !!
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>DOMDocument : ajouter des styles CSS inline à la volée</title>
</head>
<body>
<?php
// ---------------------
// 1- CONTENU HTML à parser
// ---------------------
$contentHTML = <<<EOT
<article class="artListe" id="article118">
<header>
<h1 style="padding:10px;background:yellow;">header h1 : Lorem Ipsum</h1>
</header>
<div class="artContenu">
<figure>
<img src="https://www.developpez.net/forums/avatars/256045-jreaux62.gif?dateline=1487190201" alt="jreaux62" />
</figure>
<div>
<img src="https://www.developpez.net/forums/avatars/256045-jreaux62.gif?dateline=1487190201" alt="jreaux62" />
<h1>div h1 : Sub carnifex patratis maestitiam multos</h1>
<h2>div h2 : Zenonem Attico audiebamus amaret mentitum</h2>
<h3>div h3 : Senatores se hortaretur Maximino cum</h3>
<h4>div h4 : Non et in quibusque incidissent</h4>
<p>div p : Validis Arabia hanc castrisque saepe ad contigua est Nabataeis nomine.</p>
<p class="pClass1">div p (pClass1) : Validis Arabia hanc castrisque saepe ad contigua est Nabataeis nomine.</p>
<p class="pClass1 pClass2">div p (pClass1 pClass2) : Cum neque commentum nec conduntur quoniam hoc munimentum Paleas omne.</p>
</div>
</div>
<footer>
<p>footer p : Lorem Ipsum</p>
</footer>
</article>
EOT;
// ---------------------
// 2- STYLES CSS à appliquer :
// ---------------------
$tag_css['header'] = array(
'h1' => 'font-size:240%;color:orange;',
);
$tag_css['div'] = array(
'figure' => 'border:1px solid red;margin:20px;padding:20px;',
'img' => 'border:1px solid lightblue;margin:20px;padding:20px;background:lightgreen;',
'p' => 'font-size:100%;color:grey;',
'h1' => 'font-size:180%;color:green;',
'h2' => 'font-size:160%;color:blue;',
'h3' => 'font-size:140%;color:orange;',
'h4' => 'font-size:120%;color:purple;',
);
$tag_css['footer'] = array(
'p' => 'font-size:90%;background:orange;color:#fff;text-align:center;',
);
// ---------------------
// 3- PARSER avec DOMDocument
// ---------------------
$domDocument = new DOMDocument;
// on évite l'affichage d'erreurs html en les redirigeant vers le gestionnaire d'erreurs de libxml. On sauvegarde l'ancien état dans $state.
$state = libxml_use_internal_errors(true);
// on charge le contenu HTML
$domDocument->loadHTML( $contentHTML, LIBXML_HTML_NOIMPLIED );
$domDocument->preserveWhiteSpace = false;
// on restitue l'ancien état du gestionnaire d'erreurs de libxml
libxml_use_internal_errors($state);
// discard white space
// -------------------------
// 4- Recherche par TAG NAME
// -------------------------
// 4.1- article
$domArticle = $domDocument->getElementsByTagName('article');
// ---------------------
// 4.2- childNodes de article : header / div / footer
foreach( $domArticle->item(0)->childNodes as $ArtChildNode )
{
if( !empty( $ArtChildNode->tagName ) ) // header / div / footer
{
// echo '<pre>'; print_r( $ArtChildNode->tagName ); echo '</pre>';
// -----------------
foreach( $tag_css[$ArtChildNode->tagName] as $tag => $css )
{
$nodeList = $ArtChildNode->getElementsByTagName( $tag );
foreach( $nodeList as $node )
{
$node->setAttribute( 'style', $node->getAttribute('style').$css );
}
}
// -----------------
}
}
// -------------------------
// 5- Recherche par CLASS
// -------------------------
// on crée un objet DOMXPath pour pouvoir faire des requêtes XPath sur l'arbre DOM.
$domXP = new DOMXPath($domDocument);
$nodeList = $domXP->query('//*[@class="pClass1"]');
foreach ($nodeList as $node) {
$node->setAttribute('style', $node->getAttribute('style').'font-weight:bold;color:pink;');
}
// -------------------------
// 6- on reconstitue la chaîne html en concaténant les noeuds enfant de l'élément racine.
// -------------------------
$contentHTMLCSS = '';
foreach ($domDocument->documentElement->childNodes as $node) {
$contentHTMLCSS .= $domDocument->saveHTML($node);
}
echo $contentHTMLCSS;
// -------------------------
?>
</body>
</html> |
Ce code est en partie fonctionnel :
- pour l'instant, j'y arrive à peu près avec les noms des balises.
- j'arrrive à traiter séparément les noeuds-enfants de <article> (header / div / footer)
SAUF QUE... :koi:
QUESTION 1 : Méthode
- est-ce la bonne méthode ? (car j'ai l'impression de construire une usine à gaz)
QUESTION 2 : Recherche par TAG NAME
- si on prend l'exemple des 2 balises <img>, j'aimerai pouvoir différencier (styler différemment) celle dans <figure> et celle dans <div>
- C'est-à-dire comment "déterminer" et traiter séparément les noeuds-enfants de <div class="artContenu"> ?
QUESTION 3 : Recherche par CLASS
- j'arrive à styler pour <p class="pClass1">,
- mais pas pour <p class="pClass1 pClass2"> (quand il y a plusieurs classes)
- Comment faire ? (je ne maitrise pas les query DOMXPath)
Merci de vos éclairages...
N.B. Pour info, l'Objectif : pouvoir envoyer des emails / newsletters HTML, formatés avec styles personnalisés.