47 votes

ElementTree XPath - Sélectionner un élément en fonction d'un attribut

J'ai du mal à utiliser l'attribut XPath Selector dans ElementTree, alors que je devrais pouvoir le faire selon l'instruction d'utilisation de l'attribut XPath Selector. Documentation

Voici un exemple de code

XML

<root>
 <target name="1">
    <a></a>
    <b></b>
 </target>
 <target name="2">
    <a></a>
    <b></b>
 </target>
</root>

Python

def parse(document):
    root = et.parse(document)
    for target in root.findall("//target[@name='a']"):
        print target._children

Je reçois l'exception suivante :

expected path separator ([)

1 votes

Avec ElementTree 1.2.6, les fonctionnalités xpath des attributs ne sont disponibles qu'à partir de la version 1.3.

0 votes

On dirait que findall only supporte un sous-ensemble XPath . Voir la discussion sur la liste de diffusion aquí .

17 votes

Pourquoi fermer ceci ? C'était utile pour moi... Il est loin d'être hors sujet.

37voto

Florian Bösch Points 12408

La syntaxe que vous essayez d'utiliser est nouvelle en ElementTree 1.3 .

Cette version est livrée avec Python 2.7 ou plus. Si vous avez Python 2.6 ou moins, vous avez toujours ElementTree 1.2.6 ou moins.

30voto

Albert Points 71

Il y a plusieurs problèmes dans ce code.

  1. Le constructeur ElementTree (ET en abrégé) de Python ne prend pas réellement en charge XPATH, mais seulement un sous-ensemble limité. Par exemple, il ne prend pas en charge find-from-Root Des expressions comme //target .

    Remarque : le documentation mentions " // ", mais seulement pour les enfants : Donc une expression comme .//target est valable ; //... ne l'est pas !

    Il existe une autre possibilité de mise en œuvre : lxml qui est plus riche. Il semble que la documentation soit utilisée pour le code intégré. Cela ne correspond pas/ne fonctionne pas.

  2. Le site @name La notation sélectionne xml- attributs ; le key=value dans une balise xml.

    Ainsi, ce nom-valeur doit être égal à 1 ou 2 pour sélectionner quelque chose dans le document donné. Ou bien, on peut rechercher des cibles avec un enfant élément 'a' : target[a] (pas de @).

Pour le document donné, analysé avec l'ElementTree (v1.3) intégré à Root, le code suivant est correct et fonctionne :

  • root.findall(".//target") Trouver les deux cibles
  • root.findall(".//target/a") Trouvez deux éléments a
  • root.findall(".//target[a]") Cela permet de retrouver les deux éléments cibles, car ils ont tous deux un élément a.
  • root.findall(".//target[@name='1']") Trouvez seulement le premièrement cible. Notez que les guillemets autour de 1 sont nécessaires, sinon une SyntaxError sera générée.
  • root.findall(".//target[a][@name='1']") Également valable ; pour trouver cette cible
  • root.findall(".//target[@name='1']/a") Ne trouve qu'un seul élément a ; ...

3voto

mjmarsh Points 5858

Il semble que findall ne supporte qu'un sous-ensemble de XPath. Voir la discussion sur la liste de diffusion ici

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X