Je tente de remplacer des mots cles dans un contenu HTML mais je ne veux
pas remplacer des mots dans des liens, ou situ�s a l'interieurs de
d�finitions de tags (titles, ...). Je cherche a remplacer uniquement le
texte r�el qui n'est pas situ� a l'interieur de balises <a></a>.
Je me suis donc report� sur la librairie DOM
http://us2.php.net/manual/en/book.dom.php
Mais j'ai des petits soucis avec cette librairie car je peux avoir du
cuntenu HTML dans mes $node->nodeValue meme si $node->hasChildNodes()
retourne false. Il y a meme des cas ou le $node->nodeValue est carr�ment
une balise HTML car commencant par <span ....
Voici une version r�duite de mon script:
Class Parsing
{
public static $listforbiddenTags = array("a", "img", "javascript",
"css", "script");
public static function parseNodes($node, $keyWord, $replacement)
{
$node->normalize();
if ($node->hasChildNodes())
{
$subNodes = $node->childNodes;
foreach ($subNodes as $subNode)
{
parseNodes($subNode, $keyWord, $replacement);
}
}
else
{
if (!in_array($node->parentNode->nodeName,
self::$listforbiddenTags) && $node->nodeType == XML_TEXT_NODE
&& strlen(trim($node->wholeText))>=1 && used($node->nodeValue))
{
$newelement = self::$dom->createTextNode(str_replace($keyWord,
$replacement, $node->nodeValue));
$node->parentNode->replaceChild($newelement, $node);
$node->normalize();
}
}
}
}
$doc->loadHTML($content);
$root = $doc->firstChild;
$doc->normalizeDocument();
Parsing::$dom=$doc;
Parsing::parseNodes($doc, $keyWord, $replacement);
Merci pour vos id�es :)
Cheers
DF
--
> if (!in_array($node->parentNode->nodeName,
> self::$listforbiddenTags) && $node->nodeType == XML_TEXT_NODE
> && strlen(trim($node->wholeText))>=1 && used($node->nodeValue))
Tu devrais ranger ce test dans une fonction.
> $newelement = self::$dom->createTextNode(str_replace($keyWord,
> $replacement, $node->nodeValue));
Tu peux directement modifier DomNode::nodeValue.sur le noeud parent.
J'utiliserais domxpath :
<?php
$doc = @domdocument::load('http://localhost') ;
@$doc->validate() ;
$seeker = new domxpath($doc) ;
// je ne sais pas comment filtrer par un parent d'un certain type dans
xpath.
$txtList = $seeker->evaluate('//text()') ;
foreach($txtList as $txt)
{
if(isGoodText($txt))
replaceText($txt, array('Bienvenue', 'lettre'), array('Maljour',
'courrier')) ;
}
echo $doc->saveXML() ;
function isGoodText(domnode $txt)
{
$pn = $txt->parentNode ;
return !in_array($pn->tagName, array('a')) ;
}
function replaceText(domnode $txt, $key, $replacement)
{
$content = $txt->nodeValue ;
$txt->nodeValue = str_replace($key, $replacement, $content) ;
}
--
Micka�l Wolff aka Lupus Michaelis
http://lupusmic.org
Yep, tu as raison. Les trucs grossissent, grossissent, et apres il faut
aller les ranger. :)
> J'utiliserais domxpath :
> <?php
Je vais aller regarder. La librairie DOM ne me permets pas de faire ce
que je d�sire, le HTML est mal parcouru. Par exemple, si un node
contient une balise <a> , on ne pourra pas travailler sur la chaine qui
suit la balise </a> mais qui est toujours dans le meme node.
Merci pour ton script que je vais aller tester de ce pas.
@++
DF
$content = "
<ul>
<li>title: possibility to <a href=\"www.test.com\">define the title</a>
from the link regards where this title is located</li>
</ul>
";
$doc = domdocument::load($content) ;
@$doc->validate() ;
$seeker = new domxpath($doc) ;
=> I/O warning : failed to load external entity
Bon c'est pas grave, j'ai bien avanc� avec mes expressions r�guli�res.
Cela me semble encore imparfait, mais visiblement jouer avec le DOM a
ses limites. J'ai des soucis comportementaux flagrants, du style ne pas
pouvoir accepter ce qui se situe _apres_ une balise html dans un node
qui est pr�sent� comme �tant du texte pure bien que contenant une
balise. regexp rulez for today.
@++
DF
> Bon c'est pas grave, j'ai bien avanc� avec mes expressions r�guli�res.
> Cela me semble encore imparfait, mais visiblement jouer avec le DOM a
> ses limites. J'ai des soucis comportementaux flagrants, du style ne pas
> pouvoir accepter ce qui se situe _apres_ une balise html dans un node
> qui est pr�sent� comme �tant du texte pure bien que contenant une
> balise. regexp rulez for today.
Ca d�pend de la qualit� du HTML de base. Mais noramlement, il ne
devrait pas y avoir de probl�me. J'ai essay� moi-meme d'utiliser les
regex pour parser du HTML (PHP4). C'est difficile, il faut beaucoup de
m�thode pour arriver � faire quelque chose de correct. Et si tu
n'arrives pas � utiliser le DOM, je ne pense pas que tu ais le niveau
n�cessaire.
Utilises le DOM. Je te conseillerais de lire toute la documentation
pour avoir une vue d'ensemble des fonctionnalit�s.
Ce point est malheureusement incontrolable. Le contenu saisie provient
d'un CK editor.
Mais noramlement, il ne
> devrait pas y avoir de probl�me. J'ai essay� moi-meme d'utiliser les
> regex pour parser du HTML (PHP4). C'est difficile, il faut beaucoup de
> m�thode pour arriver � faire quelque chose de correct.
Je suis arriv� a placer mes liens et tooltips sur mes mots cl�s non
situ�s dans des d�finitions de balises et n'�tant pas d�ja un lien.
> Et si tu
> n'arrives pas � utiliser le DOM, je ne pense pas que tu ais le niveau
> n�cessaire.
> Utilises le DOM. Je te conseillerais de lire toute la documentation
> pour avoir une vue d'ensemble des fonctionnalit�s.
Le DOM a ses limites qui m'empechent de faire les choses correctements.
Exemple:
content = "
<ul>
<li>title: possibility to <a href=\"www.test.com\">define the
title</a> from the link regards where this title is located</li>
</ul>
";
Class Parsing
{
public static $listforbiddenTags = array("a", "img", "javascript",
"css", "script");
public static $dom = null;
function parseNodes($node, $keyWord, $replacement)
{
if ($node->hasChildNodes())
{
$subNodes = $node->childNodes;
foreach ($subNodes as $subNode)
{
self::parseNodes($subNode, $keyWord, $replacement);
}
else if (isset($node->nodeValue))
{
$newelement =
self::$dom->createTextNode(str_replace($keyWord, $replacement,
$node->nodeValue));
$node->parentNode->replaceChild($newelement, $node);
}
}
}
$keyWord="title";
$replacement="GOT YOU";
$doc = new DomDocument('1.0', 'UTF-8');
$doc->loadHTML($content);
$root = $doc->firstChild;
//$doc->normalizeDocument();
Parsing::$dom=$doc;
Parsing::parseNodes($doc, $keyWord, $replacement);
$content=$doc->saveHTML();
print(($content));
/* OUTPUT
<br />node->nodeType => 3 <->
<br />node->value: title: possibility to
<br />node->nodeType => 3 <->
<br />node->value:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><ul>
<li>GOT YOU: possibility to <a href="www.test.com">define the title</a>
from the link regards where this title is located</li>
</ul></body></html>
/*ce qui ne va pas:
1 - le dernier title n'a pas �t� remplac�. Pire que ca, la partie
"from the link regards where this title is located" ne passe JAMAIS dans
le contenu de $node->nodeValue (j'ai fait des prints)
2 - Il y a maintenant des tags HTML suppl�mentaires, mais c'est pas
trop grave je peux les enlever apres.
Donc pour moi a ce stade, le DOM, c'est NIET.
Cheers
DF
> Exemple:
>
> content = "
> <ul>
> <li>title: possibility to <a href=\"www.test.com\">define the
> title</a> from the link regards where this title is located</li>
> </ul>
> ";
C'est normal que �a ne marche pas, le document n'est pas complet. Il
faut utiliser DomDocumentFragment pour g�rer les fragments, me semble-t-il.
J'ai absolument le m�me r�sultat avec
$content = "
<html>
<head><title>pouet</title>
</head>
<body>
<ul>
<li>title: possibility to <a href=\"www.test.com\">define the title</a>
from the link regards where this title is located</li>
</ul>
</body>
</html>
";
> Il
> faut utiliser DomDocumentFragment pour g�rer les fragments, me semble-t-il.
Le nom est prometteur, mais la page est assez peu explicite.
http://th2.php.net/manual/en/class.domdocumentfragment.php
Ne serait ce pas pour rattacher un fragment html a un node ?
@++
DF
> J'ai absolument le m�me r�sultat avec
>
> $content = "
> <html>
> <head><title>pouet</title>
> </head>
> <body>
> <ul>
> <li>title: possibility to <a href=\"www.test.com\">define the title</a>
> from the link regards where this title is located</li>
> </ul>
> </body>
> </html>
> ";
Le document est toujours incomplet. Il manque la DTD � utiliser. Si
le document g�n�re des warning ou des erreurs � l'ouverture du fichier,
ou � sa validation, l'outil DOMDocument ne fonctionnera pas.
>> Il
>> faut utiliser DomDocumentFragment pour g�rer les fragments, me semble-t-il.
>
> Le nom est prometteur, mais la page est assez peu explicite.
> http://th2.php.net/manual/en/class.domdocumentfragment.php
>
> Ne serait ce pas pour rattacher un fragment html a un node ?
Un fragment est un node comme les autres. DomDocument::adoptChild et
DomDocument::insertChild devraient t'aider.