設計筆記
通過@tdelaney答案基本上是正確的,但我要指出的Python元素樹API的一個細微差別。下面是從the lxml
tutorial報價:
元素可以包含文本:
<root>TEXT</root>
在許多XML文檔(數據爲中心的文檔),這是文本的地方可以找到的唯一地方。它由葉子標籤封裝在樹層次結構的最底部。
但是,如果用於標記的文本文件,如(X)HTML XML,文本,也可能出現不同元素之間,就在樹的中間:
<html><body>Hello<br/>World</body></html>
這裏,<br/>
標籤包圍文本。這通常被稱爲文檔樣式或混合內容XML。元素通過它們的tail
屬性支持這一點。它包含直接跟隨元素的文本,直到XML樹中的下一個元素。
這兩個屬性text
和tail
足以表示XML文檔中的任何文本內容。這樣,ElementTree API 除Element元素類之外不需要任何特殊的文本節點,這些節點往往會相當頻繁地進行(正如您從傳統DOM API中所瞭解的那樣)。
實施
考慮這些特性考慮在內,可以不強制樹輸出的文本節點檢索文檔中的文本。
#!/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>)}
如果你看看你的權利...它看起來像第4個下相關應該指向你在正確的方向... –
你有控制的XML格式?通常,分類器(如Mammals等)表示爲xml元素名稱或屬性(例如),以便xpath選擇器很容易編寫。 –
tdelaney
不,我不能更改XML。 – Alicia