Me gusta Python, pero no quiero escribir 10 líneas solo para obtener un atributo de un elemento. Tal vez solo soy yo, pero minidom no es eso mini. El código que tengo que escribir para analizar algo usando se parece mucho al código Java.

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

Me gustaría poder acceder a esto:


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

Como algo como esto:


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

Y no usar getChildren u otros métodos como ese.

24
Geo 29 sep. 2009 a las 21:22

4 respuestas

La mejor respuesta

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

Debo agregar que BeautifulSoup hace en parte lo que quieres. También hay Amara que tienen este enfoque.

21
Etienne 29 sep. 2009 a las 17:49

Pasé bastante tiempo revisando los ejemplos proporcionados anteriormente y los repositorios enumerados en pip.

La forma más fácil (y más pitónica) de analizar XML que he encontrado hasta ahora ha sido XMLToDict - https: // github. com / martinblech / xmltodict

El ejemplo de la documentación disponible en GitHub arriba se copia a continuación; Ha hecho la vida 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á buscando transformaciones inversas, ese es un asunto completamente diferente.

0
stuxnetting 9 ene. 2014 a las 08:06

Tenía la misma necesidad de un analizador xml simple y después de pasar mucho tiempo revisando diferentes bibliotecas encontré xmltramp .

Según 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

No encontré nada más fácil de usar.

2
Dobrosław Żybort 5 oct. 2012 a las 09:33

De hecho, escribí una biblioteca que hace las cosas exactamente como 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, utiliza xml.dom.minidom para realizar el análisis, pero luego camina sobre el árbol resultante y empaqueta los datos en objetos xe.

EDITAR: Bien, seguí adelante e implementé tu ejemplo en xe, para que puedas 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 "ejemplo.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 observa PyFeed, hay una clase para OPML que tiene un atributo que no es texto).

3
steveha 30 sep. 2009 a las 01:08