
Envoyé par
Doc_xhtml
Effectivement, la question revient à écrire : sélectionner les noeuds ayant pour classe "Class1" et dont les ancêtres ne sont pas des noeuds de classe Class2.
En fait, la question n'est pas correctement formulée.
Il s'agit plutôt :
« sélectionner les noeuds ayant pour classe "Class1" et dont le parent div immédiat n'est pas un noeud de classe Class2. »
Ce qui donne, en reprenant l'expression Xpath mentionnée dans ma précédente réponse
$markups = $xpath -> query(sprintf("//*[(contains(concat(' ', normalize-space(@class), ' '), ' %s ')) and (ancestor::div[1][@class != 'Class2'])]", 'Class1'));
Explications :
contains(concat(' ', normalize-space(@class), ' '), ' %s ') signifie « balise dont l'attribut class contient le terme 'Class1'. » Le paramètre %s remplace le libellé Class1 précisé après l'expression analysée de sprintf (voir cette page)
ancestor::div[1][@class != 'Class2'])]", 'Class1' signifie « dont le parent div direct a un attribut class différent de Class2 »
(Si, comme je l'ai initialement fait lors de mes essais, on omet d'indiquer l'indice [1], la recherche trouve toutes les balises class="Class1" indépendamment des div qui les contiennent.
En effet, ancestor::div[@class != 'Class2']) signifie « dont au moins un ancêtre a un attribut class autre que Class2 », ce qui est toujours le cas, à moins d'envelopper tout le document avec des balises <div class="Class2"> imbriquées.)
Remarque : Dans la mesure où le nom de la classe Class1 n'est pas variable, on peut simplifier comme suit l'expression recherchant les balises dont l'attribut class contient le terme Class1
contains(concat(' ', normalize-space(@class), ' '), ' Class1 ')
ce qui donne finalement
$markups = $xpath -> query(sprintf("//*[(contains(concat(' ', normalize-space(@class), ' '), ' Class1 ')) and (ancestor::div[1][@class != 'Class2'])]"));
PS : J'ai trouvé sur le liste de MSDN un tutoriel Xpath donnant nettement plus d'explications et d'exemples que celui de W3Shools. C'est en travaillant sur ce tuto que j'ai compris la solution à appliquer à ma question.
Partager