Zanurkuj w Pythonie/Wyszukiwanie elementów

Wyszukiwanie elementów

edytuj

Przemierzanie dokumentu XML poprzez przechodzenie przez każdy węzeł z osobna mogłoby być nużące. Jeśli poszukujesz czegoś szczególnego, co jest zagrzebane głęboko w dokumencie XML, istnieje skrót, którego możesz użyć, aby znaleźć to szybko: getElementsByTagName.

W tym podrozdziale używać będziemy pliku gramatyki binary.xml, który wygląda tak:

Przykład. 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>

Zawiera on dwa elementy ref: 'bit' i 'byte'. 'bit' może przyjmować wartości '0' lub '1', a 'byte' może się składać z ośmiu bitów.

Przykład. Wprowadzenie do 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 przyjmuje jeden argument: nazwę elementu, który chcemy znaleźć. Zwraca listę obiektów Element, odpowiednią do znalezionych elementów XML posiadających podaną nazwę. W tym przypadku znaleźliśmy dwa elementy ref.
Przykład. Każdy element możemy przeszukiwać
>>> 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. Kontynuując poprzedni przykład, pierwszy obiekt naszej listy reflist jest elementem ref 'bit'.
  2. Możemy użyć tej samej metody getElementsByTagName na tym obiekcie klasy Element, aby znaleźć wszystkie elementy <p> wewnątrz tego elementu ref 'bit'.
  3. Tak jak poprzednio metoda getElementsByTagName zwraca listę wszystkich elementów jakie znajdzie. W tym przypadku mamy dwa, po jednym na każdy bit.
Przykład. Przeszukiwanie jest właściwie rekurencyjne
>>> 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. Zauważmy różnicę pomiędzy tym i poprzednim przykładem. Poprzednio szukaliśmy elementów p wewnątrz firstref, lecz teraz szukamy elementów p wewnątrz xmldoc, czyli obiektu najwyższego poziomu reprezentującego cały dokument XML. To wyszukiwanie znajduje elementy p zagnieżdżone wewnątrz elementów ref wewnątrz głównego elementu gramatyki.
  2. Pierwsze dwa elementy p znajdują się wewnątrz pierwszego elementu ref (element ref 'bit').
  3. Ostatni element p, to ten wewnątrz drugiego elementu ref (element ref 'byte').