Zanurkuj w Pythonie/Wyszukanie bezpośrednich elementów potomnych

Wyszukanie bezpośrednich elementów potomnych

edytuj

Inną przydatną techniką przy parsowaniu dokumentów XML jest odnajdywanie wszystkich bezpośrednich elementów potomnych (dzieci) danego elementu. Na przykład w pliku gramatyki element ref może mieć szereg elementów p, a każdy z nich może zawierać wiele rzeczy, włącznie z innymi elementami p. Chcemy wyszukać tylko te elementy p, które są potomkami elementu ref, a nie elementy p, które są potomkami innych elementów p.

Pewnie myślisz, że możesz do tego celu po prostu użyć funkcji getElementsByTagName, ale niestety nie możesz. Funkcja getElementsByTagName przeszukuje rekurencyjnie i zwraca pojedyncza listę wszystkich elementów jakie znajdzie. Ponieważ elementy p mogą zawierać inne elementy p, nie możemy użyć funkcji getElementsByTagName. Zwróciłaby ona zagnieżdżone elementy p, a tego nie chcemy. Aby znaleźć tylko bezpośrednie elementy potomne, musimy to wykonać samodzielnie.

Przykład. Wyszukanie bezpośrednich elementów potomnych
    def randomChildElement(self, node):
        choices = [e for e in node.childNodes
                   if e.nodeType == e.ELEMENT_NODE] #(1) (2) (3)
        chosen = random.choice(choices)             #(4)
        return chosen
  1. Jak już widzieliśmy w przykładzie 9.9, "Pobieranie węzłów potomnych", atrybut childNodes zwraca listę wszystkich elementów potomnych danego elementu.
  2. Jednakże, jak już widziałeś w przykładzie 9.11, "Węzłami potomnymi może być także tekst", lista zwrócona przez childNodes zawiera całą różnorodność typów węzłów, włączając to węzły tekstowe. W tym wypadku szukamy jednak tylko potomków, które są elementami.
  3. Każdy węzeł posiada atrybut nodeType, który może przyjmować wartości ELEMENT_NODE, TEXT_NODE, COMMENT_NODE i wiele innych. Pełna lista możliwych wartości znajduje się w pliku __init__.py w pakiecie xml.dom. (Zajrzyj do podrozdziału 9.2, "Pakiety", aby się więcej dowiedzieć o pakietach.) Ale my jesteśmy zainteresowani węzłami, które są elementami, a więc możemy odfiltrować z listy tylko te elementy, których atrybut nodeType jest równy ELEMENT_NODE.
  4. Gdy tylko mamy już listę właściwych elementów, wybór losowego elementu jest łatwy. Python udostępnia moduł o nazwie random, który zawiera kilka funkcji. Funkcja random.choice pobiera listę z dowolną ilością elementów i zwraca losowy element. Np. jeśli element ref zawiera kilka elementów p, to choices będzie listą elementów p, a do chosen zostanie przypisany dokładnie jeden z nich, wybrany losowo.