6.5. Ricercare elementi

Attraversare documenti XML passando da un nodo all'altro può essere noioso. Se state cercando qualcosa in particolare, bene in profondità nel vostro documento XML, c'è una scorciatoia che potete usare per trovarlo più velocemente: getElementsByTagName.

Per questa sezione, useremo il file di grammatica binary.xml, che si presenta come segue:

Esempio 6.19. binary.xml

<?xml version="1.0"?>
<!DOCTYPE grammar PUBLIC "-//diveintopython.org//DTD Kant Generator Pro v1.0//EN" "kgp.dtd">
<grammar>
<ref id="bit">
  <p>0</p>
  <p>1</p>
</ref>
<ref id="byte">
  <p><xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/>\
<xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/></p>
</ref>
</grammar>

Ha due ref, 'bit' e 'byte'. Un bit può essere uno '0' od un '1' ed un byte è composto da 8 bit.

Esempio 6.20. Introduzione a getElementsByTagName

>>> from xml.dom import minidom
>>> xmldoc = minidom.parse('binary.xml')
>>> reflist = xmldoc.getElementsByTagName('ref') 1
>>> reflist
[<DOM Element: ref at 136138108>, <DOM Element: ref at 136144292>]
>>> print reflist[0].toxml()
<ref id="bit">
  <p>0</p>
  <p>1</p>
</ref>
>>> print reflist[1].toxml()
<ref id="byte">
  <p><xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/>\
<xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/></p>
</ref>
1 getElementsByTagName prende un argomento, il nome dell'elemento che volete trovare. Ritorna una lista di oggetti di tipo Element, corrispondenti agli elementi XML che hanno quel nome. In questo caso, troviamo due elementi ref.

Esempio 6.21. Ogni elemento è ricercabile

>>> firstref = reflist[0]                      1
>>> print firstref.toxml()
<ref id="bit">
  <p>0</p>
  <p>1</p>
</ref>
>>> plist = firstref.getElementsByTagName("p") 2
>>> plist
[<DOM Element: p at 136140116>, <DOM Element: p at 136142172>]
>>> print plist[0].toxml()                     3
<p>0</p>
>>> print plist[1].toxml()
<p>1</p>
1 Continuando dall'esempio precedente, il primo oggetto nella nostra lista di ref è il ref associato a 'bit'.
2 Possiamo usare lo stesso metodo getElementsByTagName su questo oggetto Element per trovare tutti gli elementi <p> all'interno dell'elemento ref associato a 'bit'.
3 Proprio come prima, il metodo getElementsByTagName restituisce una lista con tutti gli elementi trovati. In questo caso, ne abbiamo due, uno per ogni bit.

Esempio 6.22. La ricerca è ricorsiva

>>> plist = xmldoc.getElementsByTagName("p") 1
>>> plist
[<DOM Element: p at 136140116>, <DOM Element: p at 136142172>, <DOM Element: p at 136146124>]
>>> plist[0].toxml()                         2
'<p>0</p>'
>>> plist[1].toxml()
'<p>1</p>'
>>> plist[2].toxml()                         3
'<p><xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/>\
<xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/></p>'
1 Notate attentamente la differenza tra questo esempio ed il precedente. Precedentemente, stavamo cercando gli elementi p in firstref, qui stiamo cercando gli elementi p in xmldoc, cioè l'oggetto radice che rappresenta l'intero documento XML. In questo modo trova tutti gli elementi p annidati negli elementi ref all'interno del nodo radice grammar.
2 I primi due elementi p sono all'interno del primo ref (il ref associato a 'bit').
3 L'ultimo elemento p è quello all'interno del secondo ref (il ref associato a 'byte').