Zanurkuj w Pythonie/Tworzenie oddzielnych funkcji obsługi względem typu węzła: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
mNie podano opisu zmian |
poprawki |
||
Linia 1:
{{Podświetl|py}}▼
== Tworzenie oddzielnych funkcji obsługi względem typu węzła ==
Trzecim użytecznym chwytem podczas przetwarzania XML-a jest podzielenie kodu w logiczny sposób na funkcje oparte na typie węzła i nazwie elementu. Parsując dokument przetwarzamy rozmaite typy węzłów, które są reprezentowane przez obiekty Pythona. Poziom główny dokumentu jest bezpośrednio reprezentowany przez obiekt klasy <
'''Przykład 10.17. Nazwy klas parsowanych obiektów XML'''▼
{{Python/Przykład
|tekst=
>>> from xml.dom import minidom
>>> xmldoc = minidom.parse('kant.xml') #(1)
>>> xmldoc
{{samp|<xml.dom.minidom.Document instance at 0x01359DE8>}}
>>> xmldoc.__class__ #(2)
{{samp|<class xml.dom.minidom.Document at 0x01105D40>}}
>>> xmldoc.__class__.__name__ #(3)
{{samp|'Document'}}
# Załóżmy na moment, że
# Jak powiedzieliśmy w
# Ponadto
}}
To fajnie, możemy pobrać nazwę klasy dowolnego węzła XML-a (ponieważ węzły są reprezentowane przez Pythonowe obiekty). Jak można wykorzystać tę zaletę, aby rozdzielić logikę parsowania dla każdego typu węzła? Odpowiedzią jest <
{{Python/Przykład
|tekst=
<pre>
</pre>
# Od razu,
▲ def parse(self, node):
# Teraz, jeśli potraktujemy tę nazwę jako nazwę funkcji, otrzymamy dzięki <
▲ parseMethod = getattr(self, "parse_%s" % node.__class__.__name__) #(1) (2)
# Ostatecznie, możemy wywołać tę funkcję, przekazując sam <
▲ parseMethod(node) #(3)
}}
{{Python/Przykład
▲# Od razu, zauważ, że konstruujemy dłuższy napis oparty na nazwie klasy przekazanego węzła (jako argument <tt>node</tt>). Zatem, jeśli przekażemy węzeł <tt>Document</tt>-u, konstruujemy napis <tt>'parse_Document'</tt> itd.
▲# Teraz, jeśli potraktujemy tę nazwę jako nazwę funkcji, otrzymamy dzięki <tt>getattr</tt> referencję do funkcji.
|tekst=
▲# Ostatecznie, możemy wywołać tę funkcję, przekazując sam <tt>node</tt> jako argument. Następny przykład przedstawia definicję tych funkcji.
<pre>
▲'''Przykład 10.19. Funkcje wywoływane przez funkcję pośredniczącą <tt>parse</tt>'''
▲ self.parse(node.documentElement)
▲ def parse_Text(self, node): #(2)
▲ text = node.data
▲ if self.capitalizeNextWord:
▲ self.pieces.append(text[0].upper())
▲ self.pieces.append(text[1:])
▲ self.capitalizeNextWord = 0
▲ else:
▲ self.pieces.append(text)
▲ def parse_Comment(self, node): #(3)
▲ pass
def parse_Element(self, node): #(4)▼
handlerMethod = getattr(self, "do_%s" % node.tagName)▼
handlerMethod(node)▼
# <tt>parse_Document</tt> jest wywołany tylko raz, ponieważ jest tylko jeden węzeł klasy <tt>Document</tt> w dokumencie XML i tylko jeden obiekt klasy <tt>Document</tt> w przeparsowanej reprezentacji XML-a. Tu po prostu idziemy dalej i parsujemy część główną pliku gramatyki.▼
# <tt>parse_Text</tt> jest wywoływany tylko na węzłach reprezentujących fragmenty tekstu. Funkcja wykonuje kilka specjalnych operacji związanych z automatycznym wstawianiem dużej litery na początku słowa pierwszego zdania, ale w innym wypadku po prostu dodaje reprezentowany tekst do listy.▼
# <tt>parse_Comment</tt> jest tylko "przejażdżką"; metoda ta nic nie robi, ponieważ nie musimy się troszczyć o komentarze wstawione w plikach definiującym gramatykę. Pomimo tego, zauważ, że nadal musimy zdefniować funkcję i wyraźnie stwierdzić, żeby nic nie robiła. Jeśli funkcja nie będzie istniała, funkcja <tt>parse</tt> nawali tak szybko, jak napotka się na komentarz, ponieważ będzie próbowała znaleźć nieistniejącą funkcję <tt>parse_Comment</tt>. Definiując oddzielną funkcję dla każdego typu węzła, nawet jeśli nam ta funkcja nie jest potrzebna, pozwalamy ogólnej funkcji parsującej być prostą i krótką.▼
</pre>
# Metoda <tt>parse_Element</tt> jest faktycznie funkcją pośredniczącą, opartą na nazwie znacznika elementu. Idea jest taka sama: weź odróżniające się od siebie elementy (elementy, które różnią się nazwą znacznika) i wyślij je do odpowiedniej, odrębnej funkcji. Konstruujemy napis typu <tt>'do_xref'</tt> (dla znacznika <tt><xref></tt>), znajdujemy funkcję o takiej nazwie i wywołujemy ją. I tak dalej, dla każdego innej nazwy znacznika, która zostanie znaleziona, oczywiście w pliku gramatyki (czyli znaczniki <tt><nowiki><p></nowiki></tt>, czy też <tt><choice></tt>).▼
▲# <
▲# <
▲# <
▲# Metoda <
}}
W tym przykładzie funkcja pośrednicząca <
<noinclude>
{{Nawigacja|Zanurkuj w Pythonie|
[[../Wyszukanie bezpośrednich elementów potomnych/]]|
[[../Obsługa argumentów linii poleceń
}}
▲{{Podświetl|py}}
</noinclude>
|