2009-12-19 16 views
16

J'essaye d'analyser du HTML avec DOM en PHP, mais j'ai quelques problèmes. D'abord, au cas où cela changerait la solution, le HTML que j'ai n'est pas une page complète, mais plutôt une partie seulement.Comment analyser partiellement le HTML?

<!-- This is the HTML that I have --><a href='/games/'> 
<div id='game'> 
<img src='http://images.example.com/games.gif' width='300' height='137' border='0'> 
<br><b> Game </b> 
</div> 
<div id='double'> 
<img src='http://images.example.com/double.gif' width='300' height='27' border='0' alt='' title=''> 
</div> 
</a> 

Maintenant, je suis en train d'obtenir seulement le div avec l'id double. J'ai essayé le code suivant, mais il ne semble pas fonctionner correctement. Que pourrais-je faire de mal?

//The HTML has been loaded into the variable $html 
$dom=new domDocument; 
$dom->loadHTML($html); 
$dom->preserveWhiteSpace = false; 
$keepme = $dom->getElementById('double'); 

$contents = '<div style="text-align:center">'.$keepme.'</a></div>'; 
echo $contents; 
+0

Que fait-il ou ne pas faire? –

Répondre

13

Je pense que DOMDocument::getElementById ne fonctionnera pas dans votre cas: (citant)

Pour que cette fonction fonctionne, vous besoin soit de définir certains attributs ID avec DOMElement::setIdAttribute ou une DTD qui définit un attribut à de type ID.
Dans le dernier cas, vous devrez valider votre document avec DOMDocument::validate ou DOMDocument->validateOnParse avant en utilisant cette fonction.


Une solution qui pourrait fonctionner utilise une partie XPath query pour extraire l'élément que vous recherchez.

Tout d'abord, nous allons charger la partie HTML, comme vous la première fois:

$dom=new domDocument; 
$dom->loadHTML($html); 
var_dump($dom->saveHTML()); 

Le var_dump est ici seulement pour prouver que la partie HTML a été chargé avec succès - à en juger par sa sortie, il a .


Ensuite, instancier la classe DOMXPath, et l'utiliser pour interroger l'élément que vous voulez obtenir:

$xpath = new DOMXpath($dom); 
$result = $xpath->query("//*[@id = 'double']"); 
$keepme = $result->item(0); 

Nous avons maintenant à l'élément que vous voulez ;-)


Mais , pour injecter son contenu HTML dans un autre segment HTML, il faut d'abord récupérer son contenu HTML.

Je ne me souviens pas de façon « facile » de le faire, mais quelque chose comme ça l'affaire pourrais-:

$tempDom = new DOMDocument(); 
$tempImported = $tempDom->importNode($keepme, true); 
$tempDom->appendChild($tempImported); 
$newHtml = $tempDom->saveHTML(); 
var_dump($newHtml); 

Et ... Nous avons le contenu HTML de votre double<div>:

string '<div id="double"> 
<img src="http://images.example.com/double.gif" width="300" height="27" border="0" alt="" title=""> 
</div> 
' (length=125) 


maintenant, il vous suffit de faire ce que vous voulez avec elle ;-)

0

HTML Tidy doit être capable de "corriger" les documents HTML brisés et fragmentés, en les transformant en quelque chose qui peut être analysé avec d'autres outils

http://devzone.zend.com/article/761

L'extension Tidy est nouveau dans PHP 5, et est disponible à partir de la version PHP 5.0b3 vers le haut. Il est basé sur la bibliothèque TidyLib et permet au développeur de valider, de réparation et analyse syntaxique HTML, XHTML et documents XML à partir de PHP.

3

De DomDocument::getElementById

Pour que cette fonction fonctionne, vous aurez besoin soit de définir certains attributs ID avec DOMElement :: setIdAttribute ou une DTD qui définit un attribut à de type ID . Dans le dernier cas, vous devrez valider votre document avec DOMDocument :: validate ou DOMDocument-> validateOnParse avant en utilisant cette fonction.

Pour des informations supplémentaires

Et comme quelqu'un mentionnera le faire avec une expression régulière, est ici tôt ou tard le modèle que vous pouvez utiliser: /<div id='double'>(.*)<\/div>/simU

En outre Vous pouvez simplement utiliser des fonctions de chaîne régulières pour extraire la partie div, par ex.

$div = strstr($html, '<div id="double">'); 
$div = substr($div, 0, strpos($div, '</div>') + 6); 
echo $div; 

Bien que je suis d'accord, vous ne devriez pas utiliser RegEx ou fonctions de chaîne pour analyse syntaxique HTML ou XML, je trouve qu'il est tout à fait correct de le faire, tant que votre seule préoccupation est d'obtenir ce single div des fragments. Rester simple.

+1

À moins qu'il y ait des balises div imbriquées bien sûr.Les expressions régulières ne sont * pas * pour l'analyse du code HTML. – troelskn

+0

Je serais d'accord s'il était en train de * analyser * ce fragment. mais il veut juste en extraire une pièce clairement définie. Ce n'est pas comme s'il traversait le DOM, donc je suppose que c'est correct de traiter le fragment comme une chaîne. – Gordon

+0

En outre, je l'ai déjà indiqué à SimpleHTML dans la première phrase. – Gordon

0

Un document XML ne peut avoir qu'un seul élément au niveau racine. Probablement, l'analyseur HTML a une exigence similaire. Essayez d'envelopper le contenu dans une balise <body/>.

Semble que c'est quelque chose d'autre. This page décrit ce qui peut être la cause. Je vous recommande d'utiliser XPath pour obtenir l'élément.

-1

Le fragment est HTML, mais pour être analysé via DOM, il devrait XHTML. Chaque étiquette ouverte doit être fermée.

Dans votre cas, cela signifie que vous devez remplacer <br> avec <br /> et <img ... > avec <img ... />

+0

Ce n'est pas vrai. $ Dom-> loadHTML ("


") fonctionne très bien et n'échoue pas l'analyse syntaxique. En fait, $ dom-> saveXML() vous montrera la sortie avec des balises correctement fermées. –

+0

Tout dépend de la bibliothèque que vous utilisez. En python: xml.dom.minidom.parseString ("
") -> renvoie une exception. xml.dom.minidom.parseString ("
") fonctionne. Je préférerais avoir l'entrée dans le format correct en premier lieu que de compter sur une bibliothèque pour analyser l'entrée incorrecte comme je l'espère. – filippo

Questions connexes