Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Probleme de Librairie DOM

0 views
Skip to first unread message

DublinFrench

unread,
Oct 4, 2009, 9:12:17 AM10/4/09
to
Salut

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


--

Mickael Wolff

unread,
Oct 5, 2009, 1:20:19 AM10/5/09
to
DublinFrench wrote:

> 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

DublinFrench

unread,
Oct 5, 2009, 4:27:50 AM10/5/09
to
Mickael Wolff wrote:
>> 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.

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

DublinFrench

unread,
Oct 5, 2009, 10:46:42 AM10/5/09
to
DublinFrench wrote:
> Merci pour ton script que je vais aller tester de ce pas.


$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

Mickael Wolff

unread,
Oct 5, 2009, 6:40:22 PM10/5/09
to
DublinFrench wrote:
>
> $doc = domdocument::load($content) ;

> => I/O warning : failed to load external entity
Il FAUT lire la documentation. Tu remarqueras que jevdonnais un
chemin vers un fichier, pas le contenu.

> 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.

DublinFrench

unread,
Oct 6, 2009, 5:26:31 AM10/6/09
to
Mickael Wolff wrote:

> DublinFrench wrote:
> Ca d�pend de la qualit� du HTML de base.

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

Mickael Wolff

unread,
Oct 6, 2009, 9:15:11 AM10/6/09
to
DublinFrench wrote:

> 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.

DublinFrench

unread,
Oct 6, 2009, 6:59:42 PM10/6/09
to
Mickael Wolff wrote:
> DublinFrench wrote:
>> 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.

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

Mickael Wolff

unread,
Oct 7, 2009, 3:12:41 PM10/7/09
to
DublinFrench wrote:

> 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.

0 new messages