9.6. Acceso a atributos de elementos

Los elementos de XML pueden tener uno o más atributos, y es increíblemente sencillo acceder a ellos una vez analizado el documento XML.

En esta sección usaremos el fichero de gramática binary.xml que vio en la sección anterior.

nota
Esta sección puede ser un poco confusa, debido a que la terminología se solapa. Los elementos de documentos XML tienen atributos, y los objetos de Python también. Cuando analizamos un documento XML obtenemos un montón de objetos de Python que representan todas las partes del documento XML, y algunos de estos objetos de Python representan atributos de los elementos de XML. Pero los objetos (de Python) que representan los atributos (de XML) también tienen atributos (de Python), que se usan para acceder a varias partes del atributo (de XML) que representa el objeto. Le dije que era confuso. Estoy abierto a sugerencias para distinguirlos con más claridad.

Ejemplo 9.24. Acceso a los atributos de un elemento

>>> xmldoc = minidom.parse('binary.xml')
>>> reflist = xmldoc.getElementsByTagName('ref')
>>> bitref = reflist[0]
>>> print bitref.toxml()
<ref id="bit">
  <p>0</p>
  <p>1</p>
</ref>
>>> bitref.attributes          1
<xml.dom.minidom.NamedNodeMap instance at 0x81e0c9c>
>>> bitref.attributes.keys()   2 3
[u'id']
>>> bitref.attributes.values() 4
[<xml.dom.minidom.Attr instance at 0x81d5044>]
>>> bitref.attributes["id"]    5
<xml.dom.minidom.Attr instance at 0x81d5044>
1 Cada objeto Element tiene un atributo llamado attributes, que es un objeto NamedNodeMap. Suena feo pero no lo es, porque NamedNodeMap es un objeto que actúa como un diccionario, así que ya sabemos cómo usarlo.
2 Si tratamos el NamedNodeMap como un diccionario, podemos obtener una lista de nombres de los atributos de este elemento usando attributes.keys(). Este elemento sólo tiene un atributo, 'id'.
3 Los nombres de los atributos se almacenan en unicode, como cualquier otro texto dentro de un documento XML.
4 De nuevo tratamos el NamedNodeMap como un diccionario para obtener una lista de valores de los atributos usando attributes.values(). Los valores en sí son objetos, de tipo Attr. Verá cómo obtener información útil de este objeto en el siguiente ejemplo.
5 Seguimos tratando el NamedNodeMap como un diccionario y ahora accedemos a un atributo individual, usando la sintaxis normal de un diccionario. (Los lectores que hayan prestado muchísima atención ya sabrán cómo hace este magnífico truco la clase NamedNodeMap: definiendo un método especial __getitem__. Otros lectores pueden confortarse con el hecho de que no necesitan entender su funcionamiento para poder usarlo de forma efectiva.

Ejemplo 9.25. Acceso a atributos individuales

>>> a = bitref.attributes["id"]
>>> a
<xml.dom.minidom.Attr instance at 0x81d5044>
>>> a.name  1
u'id'
>>> a.value 2
u'bit'
1 El objeto Attr representa un único atributo de XML de un único elemento XML. El nombre del atributo (el mismo nombre que usamos para encontrar el objeto en el pseudodiccionario NamedNodeMap bitref.attributes) se almacena en a.name.
2 El valor del texto de este atributo XML se almacena en a.value.
nota
Al igual que un diccionario, los atributos de un elemento XML no tienen orden. Puede que los atributos estén listados en un cierto orden en el documento XML original, y puede que los objetos Attr estén listados en un cierto orden cuando se convierta el documento XML en objetos de Python, pero estos órdenes son arbitrarios y no deberían tener un significado especial. Siempre debería acceder a los atributos por su nombre, como claves de un diccionario.