tutorial library example etree dict create python elementtree

python - library - ElementTree XPath-Elemento selecto basado en el atributo



xml etree elementtree tutorial (3)

Tengo problemas para usar el atributo XPath Selector en ElementTree, que debería poder hacer de acuerdo con la Documentación

Aquí hay un código de muestra

XML

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

Pitón

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

Estoy recibiendo la siguiente excepción:

expected path separator ([)


Parece que findall solo admite un subconjunto de XPath. Vea la discusión de la lista de correo aquí


La sintaxis que intentas usar es nueva en ElementTree 1.3 .

Dicha versión se envía con Python 2.7 o superior. Si tiene Python 2.6 o menos, todavía tiene ElementTree 1.2.6 o menos.


Hay varios problemas en este código.

  1. Python''s buildin ElementTree (ET por sus siglas en inglés) no tiene soporte real de XPATH; solo un subconjunto limitado Por ejemplo, no admite expresiones de búsqueda de raíz como //target .

    Aviso: la documentación menciona " // ", pero solo para niños: Entonces una expresión como .//target es válida; //... ¡no!

    Hay una implementación alternativa: lxml que es más rico. Es costuras que se utiliza la documentación para el código incorporado. Eso no coincide / funciona.

  2. La notación @name selecciona atributos xml; la expresión key=value dentro de una etiqueta xml.

    Entonces ese nombre-valor tiene que ser 1 o 2 para seleccionar algo en el documento dado. O bien, uno puede buscar objetivos con un elemento secundario ''a'' : target[a] (no @).

Para el documento dado, analizado con el ElementTree incorporado (v1.3) a la raíz, el siguiente código es correcto y funciona:

  • root.findall(".//target") Encuentra ambos objetivos
  • root.findall(".//target/a") Encuentra dos elementos
  • root.findall(".//target[a]") Esto encuentra ambos elemento-objetivo de nuevo, ya que ambos tienen un elemento a
  • root.findall(".//target[@name=''1'']") Encuentra solo el primer objetivo. Tenga en cuenta que las cotizaciones alrededor de 1 son necesarias; sino que se genera un SyntaxError
  • root.findall(".//target[a][@name=''1'']") También válido; para encontrar ese objetivo
  • root.findall(".//target[@name=''1'']/a") Encuentra solo un elemento a; ...