2009-09-29 12 views
24

Me gusta Python, pero no quiero escribir 10 líneas solo para obtener un atributo de un elemento. Quizás soy solo yo, pero minidom no es ese mini. El código que tengo que escribir para analizar algo usando se parece mucho al código Java.¿Hay algún analizador XML de Python diseñado con humanos en mente?

¿Hay algo que es más user-friendly? ¿Algo con operadores sobrecargados y que asigna elementos a los objetos?

Me gustaría ser capaz de acceder a este:


<root> 
<node value="30">text</node> 
</root> 

como algo parecido a esto:


obj = parse(xml_string) 
print obj.node.value 

y no usar getChildren o algunos otros métodos por el estilo.

+1

¿XPath cuenta como fácil de usar? http://stackoverflow.com/questions/8692/how-to-use-xpath-in-python – Welbog

+0

¡Estaría muy interesado en una versión de Java de esto! – Federer

Respuesta

22

Deberías echar un vistazo a ElementTree. No está haciendo exactamente lo que quieres, pero es mucho mejor que minidom. Si recuerdo correctamente, a partir de Python 2.4, está incluido en las bibliotecas estándar. Para mayor velocidad, use cElementTree. Para obtener más velocidad (y más funciones), puede usar lxml (consulte la API de Objectify para conocer sus necesidades/enfoque).

Debo añadir que BeautifulSoup hacen en parte lo que usted desea. También hay Amara que tienen este enfoque.

+3

+1, ElementTree es excelente. – Mark

+0

ElementTree es excelente. –

+0

De acuerdo, ElementTree es súper fácil de usar. No tan genial con espacios de nombres extravagantes (todavía) pero cada vez mejor. Evite minidom cuando sea posible. –

3

De hecho, escribí una biblioteca que hace las cosas exactamente de la manera en que lo imaginaste. La biblioteca se llama "xe" y puede obtenerla de: http://home.avvanta.com/~steveha/xe.html

xe puede importar XML para permitirle trabajar con los datos de forma orientada a objetos. En realidad usa xml.dom.minidom para hacer el análisis sintáctico, pero luego camina sobre el árbol resultante y empaqueta los datos en objetos xe.

EDITAR: Bien, seguí adelante e implementé su ejemplo en xe, para que pueda ver cómo funciona. Aquí hay clases para implementar el XML que mostró:

import xe 

class Node(xe.TextElement): 
    def __init__(self, text="", value=None): 
     xe.TextElement.__init__(self, "node", text) 
     if value is not None: 
      self.attrs["value"] = value 

class Root(xe.NestElement): 
    def __init__(self): 
     xe.NestElement.__init__(self, "root") 
     self.node = Node() 

Y aquí hay un ejemplo del uso de lo anterior. Puse su XML de muestra en un archivo llamado "example.xml", pero también podría ponerlo en una cadena y pasar la cadena.

>>> root = Root() 
>>> print root 
<root/> 
>>> root.import_xml("example.xml") 
<Root object at 0xb7e0c52c> 
>>> print root 
<root> 
    <node value="30">text</node> 
</root> 
>>> print root.node.attrs["value"] 
30 
>>> 

Tenga en cuenta que en este ejemplo, el tipo de "valor" será una cadena. Si realmente necesita atributos de otro tipo, eso también es posible con un poco de trabajo, pero no me molesté en este ejemplo. (Si miras a PyFeed, hay una clase para OPML que tiene un atributo que no es texto.)

2

Tenía la misma necesidad de un analizador xml simple y después de un largo tiempo dedicado a verificar diferentes bibliotecas encontré xmltramp.

Basado en su ejemplo xml:

import xmltramp 

xml_string = """<root> 
<node value="30">text</node> 
</root>""" 

obj = xmltramp.parse(xml_string) 
print obj.node('value')    # 30 
print str(obj.node)     # text 

que no fundó nada más fácil de usar.

0

Pasé bastante tiempo revisando los ejemplos proporcionados anteriormente y a través de los repositorios enumerados en pip.

La forma (Pythonic más y) más fácil de XML de análisis que he encontrado hasta el momento ha sido XMLToDict - https://github.com/martinblech/xmltodict

El ejemplo de la documentación disponible en GitHub anterior es copia-pegado abajo; Ha hecho que la vida sea MUY simple y FÁCIL para MUCHAS veces;

>>> doc = xmltodict.parse(""" 
... <mydocument has="an attribute"> 
... <and> 
...  <many>elements</many> 
...  <many>more elements</many> 
... </and> 
... <plus a="complex"> 
...  element as well 
... </plus> 
... </mydocument> 
... """) 
>>> 
>>> doc['mydocument']['@has'] 
u'an attribute' 
>>> doc['mydocument']['and']['many'] 
[u'elements', u'more elements'] 
>>> doc['mydocument']['plus']['@a'] 
u'complex' 
>>> doc['mydocument']['plus']['#text'] 
u'element as well' 

Funciona muy bien y me dio justo lo que estaba buscando. Sin embargo, si estás viendo transformaciones inversas, esa es una cuestión completamente diferente.

Cuestiones relacionadas