uwaga Projekt
Odpowiedź przez @tdelaney jest w zasadzie w porządku, ale chcę zwrócić uwagę na jeden niuans Python elementem drzewa API. Oto cytat z the lxml
tutorial:
Elementy mogą zawierać tekst:
<root>TEXT</root>
w wielu dokumentach XML (dokumenty danych-centric), jest to jedyne miejsce, gdzie tekst można znaleźć. Jest enkapsulowany przez znacznik liści na samym dole hierarchii drzewa.
Jednakże, jeśli XML jest używany do oznaczonych dokumentów tekstowych, takich jak (X) HTML, tekst może również pojawić się pomiędzy różnymi elementami, w samym środku drzewa:
<html><body>Hello<br/>World</body></html>
Tutaj tag <br/>
jest otoczony tekstem. Jest to często określane jako XML w stylu dokumentu lub XML o mieszanej zawartości. Elementy obsługują to poprzez ich właściwość tail
. Zawiera tekst bezpośrednio podążający za elementem, aż do następnego elementu w drzewie XML.
Obie właściwości: text
i tail
są wystarczające do reprezentowania dowolnej treści tekstowej w dokumencie XML. W ten sposób ElementTree API nie wymaga żadnych specjalnych węzłów tekstowych oprócz klasy Elementów, które mają tendencję do wchodzenia w drogę dość często (jak można się domyślić z klasycznych API DOM).
Realizacja
Biorąc pod uwagę te właściwości możliwe jest odzyskanie tekstu dokumentu bez wymuszania drzewo do węzłów tekstowych wyjście.
#!/usr/bin/env python3.3
import itertools
from pprint import pprint
try:
from lxml import etree
except ImportError:
from xml.etree import cElementTree as etree
def textAndElement(node):
'''In py33+ recursive generators are easy'''
yield node
text = node.text.strip() if node.text else None
if text:
yield text
for child in node:
yield from textAndElement(child)
tail = node.tail.strip() if node.tail else None
if tail:
yield tail
if __name__ == '__main__':
xml = '''
<species>
Mammals: <dog/> <cat/>
Reptiles: <snake/> <turtle/>
Birds: <seagull/> <owl/>
</species>
'''
doc = etree.fromstring(xml)
pprint(list(textAndElement(doc)))
#[<Element species at 0x7f2c538727d0>,
#'Mammals:',
#<Element dog at 0x7f2c538728c0>,
#<Element cat at 0x7f2c53872910>,
#'Reptiles:',
#<Element snake at 0x7f2c53872960>,
#<Element turtle at 0x7f2c538729b0>,
#'Birds:',
#<Element seagull at 0x7f2c53872a00>,
#<Element owl at 0x7f2c53872a50>]
gen = textAndElement(doc)
next(gen) # skip root
groups = []
for _, g in itertools.groupby(gen, type):
groups.append(tuple(g))
pprint(dict(zip(*[iter(groups)] * 2)))
#{('Birds:',): (<Element seagull at 0x7fc37f38aaa0>,
# <Element owl at 0x7fc37f38a820>),
#('Mammals:',): (<Element dog at 0x7fc37f38a960>,
# <Element cat at 0x7fc37f38a9b0>),
#('Reptiles:',): (<Element snake at 0x7fc37f38aa00>,
# <Element turtle at 0x7fc37f38aa50>)}
jeśli spojrzeć na po prawej ... wygląda na to, 4. jeden antypodów powiązany powinien wskazać we właściwym kierunku ... –
masz kontrolę formacie xml?Zwykle klasyfikatory, takie jak ssaki itp., Są wyrażane jako nazwy lub atrybuty elementu xml (np.), dzięki czemu selektory xpath są łatwo zapisywane. –
tdelaney
Nie, nie mogę zmienić kodu XML. – Alicia