6.6. Accedere agli attributi di un elemento

Gli elementi XML possono avere uno o più attributi ed è incredibilmente semplice accedervi una volta che avete analizzato il documento XML.

Per questa sezione, useremo il file di grammatica binary.xml che abbiamo visto nella sezione precedente.

Nota
Questa sezione potrebbe risultare un po' confusa a causa della sovrapposizione nella terminologia. Gli elementi in un documento XML hanno degli attributi ed anche gli oggetti Python hanno degli attributi. Quando analizziamo un documento XML, otteniamo un gruppo di oggetti Python che rappresentano tutti i pezzi del documento XML ed alcuni di questi oggetti rappresentano gli attributi degli elementi XML. Ma anche gli oggetti (Python) che rappresentano gli attributi (XML) hanno attributi, che vengono utilizzati per accedere alle varie parti degli attributi (XML) che l'oggetto rappresenta. Ve l'ho detto che vi avrebbe confuso. Sono aperto a suggerimenti su come distinguere le due cose in maniera più chiara.

Esempio 6.23. Accedere agli attributi di 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 Ogni oggetto di tipo Element ha un attributo chiamato attributes, che è un oggetto NamedNodeMap. Suona spaventoso, ma non lo è, perché una NamedNodeMap è un oggetto che si comporta come un dizionario, dunque già sapete come usarla.
2 Trattando la NamedNodeMap come un dizionario, possiamo ottenere una lista dei nomi degli attributi di questo elemento usando attributes.keys(). Questo elemento ha un solo attributo, 'id'.
3 I nomi degli attributi, come tutti gli altri testi in un documento XML, sono memorizzati in unicode.
4 Ancora, trattando la NamedNodeMap come un dizionario, possiamo ottenere una lista dei valori degli attributi utilizzando attributes.values(). I valori sono essi stessi degli oggetti, di tipo Attr. Vedremo come ottenere utili informazioni da questi oggetti nel prossimo esempio.
5 Continuando a trattare la NamedNodeMap come un dizionario, possiamo accedere ad un singolo attributo tramite il nome, usando la normale sintassi dei dizionari. I lettori che hanno prestato estrema attenzione già sapranno come la classe NamedNodeMap riesce a fare questo trucco: definendo il metodo speciale __getitem__. Gli altri lettori si possono tranquillizzare perché non hanno bisogno di sapere come funzioni per usarla.

Esempio 6.24. Accedere agli attributi individuali

>>> a = bitref.attributes["id"]
>>> a
<xml.dom.minidom.Attr instance at 0x81d5044>
>>> a.name  1
u'id'
>>> a.value 2
u'bit'
1 L'oggetto Attr rappresenta completamente un singolo attributo XML di un singolo elemento XML. Il nome dell'attributo (lo stesso nome che abbiamo usato per trovare questo oggetto nello pseudo-dizionario NamedNodeMap bitref.attributes) è memorizzato in a.name.
2 Il valore di testo dell'attributo XML è memorizzato in a.value.
Nota
Come un dizionario, gli attributi di un elemento XML non hanno ordinamento. Gli attributi possono essere elencati in un certo ordine nel documento XML originale e gli oggetti Attr possono essere elencati in un certo ordine quando il documento XML viene interpretato in oggetti Python, ma questi ordinamenti sono arbitrari e non dovrebbero avere alcun significato particolare. Dovreste sempre accedere agli attributi in base al nome, come nel caso delle chiavi di un dizionario.