2010-11-22 18 views
2

considérant ce qui suit: (mélange de <br> et <br/>)XPath: sélectionnez les nœuds de texte avant et après balises de saut

text1 
<br> 
text2 
<br/> 
text3 
<br/> 
text4 
<br> 
text5 

Comment puis-je localiser chaque noeud texte?

Je pense à quelque chose qui correspond à la condition de précéder OU suivre une balise br .... mais pas sûr si <br> et <br/> sont traités différemment dans xpath.

+3

Cela ne ressemble pas à du code XML valide pour que XPATH fonctionne. – geoffc

+0

Ce n'est * pas * une question XPAth du tout - votre texte n'est pas bien formé XML! Apprenez que XPath peut être utilisé uniquement sur un document XML bien formé ou un fragment XML. –

+0

J'ai trouvé votre édition très choquante et je l'ai signalée. J'ai roll soutenu. Je pense qu'il devrait être évident pour vous que ce Xpath n'est pas bien formé, mais traitant de HTML à partir du Web, c'est juste un fait et le besoin de traiter ces cas irréguliers. – KJW

Répondre

5

DOMDocument « s loadHTML() méthode fonctionne bien avec des fragments HTML non valides, afin que vous puissiez utilisez DOMXPath de cette façon:

<?php 

$html = 'text1 
<br> 
text2 
<br/> 
text3 
<br/> 
text4 
<br> 
text5'; 

echo "<pre>" . htmlentities($html) . "</pre><br>\n"; 

$dom = new DOMDocument(); 
// loadHtml() needs mb_convert_encoding() to work well with UTF-8 encoding 
$dom->loadHtml(mb_convert_encoding($html, 'HTML-ENTITIES', "UTF-8")); 

$xpath = new DOMXPath($dom); 

echo "Text nodes preceding br:"; 
foreach($xpath->query('//text()[(following::br)]') as $node) 
{ 
    var_dump($node->wholeText); 
} 

echo "Text nodes following br:"; 
foreach($xpath->query('//text()[(preceding::br)]') as $node) 
{ 
    var_dump($node->wholeText); 
} 

echo "Text nodes following OR preceding br:"; 
foreach($xpath->query('//text()[(following::br) or (preceding::br)]') as $node) 
{ 
    var_dump($node->wholeText); 
} 
+0

cela obtiendrait simplement tous les nœuds de texte autres que le cas d'échantillon illustré. – KJW

+0

@Kim Vous avez raison, j'ai simplement négligé cette exigence. Edité, maintenant ça fonctionne comme ça. –

+0

merci, je pense que cela correspond à la spécification. Je pense aussi à combiner ceci pour former quelque chose comme // text() [(suivant :: br OR preceiding :: br)]. – KJW

0

Votre exemple n'est pas XML valide contre lequel une requête XPath peut être exécuté - ni des
éléments sont toujours fermés.

Cependant, en général pour sélectionner que vous utilisez le prédicat de type de noeud, quelque chose comme // br/texte()

+0

Bonne réponse, +1. –

+1

J'ai downvoted cette question parce que ma définition d'une bonne réponse diffère évidemment de Dimitre. Je downvote les réponses dans lesquelles aucune solution ou approche n'est fournie et les réponses qui semblent être plus d'un commentaire que celle d'une réponse qui résulte de la résolution active d'un problème plutôt que d'énoncer l'évidence ou la lecture du dictionnaire. Vous devez comprendre le sens implicite derrière les questions, et ce n'est pas toujours facile de le faire correctement, et certaines personnes auront plus de difficulté. À la fin de la journée, j'invoque des réponses qui aident les autres utilisateurs à réfléchir à la même question que moi. – KJW