与LXML和Python
解析空白XML标记时,格式为XML文档解析:与LXML和Python
<Car>
<Color>Blue</Color>
<Make>Chevy</Make>
<Model>Camaro</Model>
</Car>
我使用下面的代码:
carData = element.xpath('//Root/Foo/Bar/Car/node()[text()]')
parsedCarData = [{field.tag: field.text for field in carData} for action in carData]
print parsedCarData[0]['Color'] #Blue
此代码不会,如果一个标签是空的工作如:
<Car>
<Color>Blue</Color>
<Make>Chevy</Make>
<Model/>
</Car>
使用相同的代码如上:
carData = element.xpath('//Root/Foo/Bar/Car/node()[text()]')
parsedCarData = [{field.tag: field.text for field in carData} for action in carData]
print parsedCarData[0]['Model'] #Key Error
我该如何解析这个空白标记。
你在[text()]
过滤器仅其中明确要求对于具有文本节点元素把他们...然后你不高兴时,它不给你没有文字节点的元素?
离开过滤掉,你会得到你的模型元素:
>>> s='''
... <root>
... <Car>
... <Color>Blue</Color>
... <Make>Chevy</Make>
... <Model/>
... </Car>
... </root>'''
>>> e = lxml.etree.fromstring(s)
>>> carData = e.xpath('Car/node()')
>>> carData
[<Element Color at 0x23a5460>, <Element Make at 0x23a54b0>, <Element Model at 0x23a5500>]
>>> dict(((e.tag, e.text) for e in carData))
{'Color': 'Blue', 'Make': 'Chevy', 'Model': None}
那说 - 如果你的近期目标是遍历树的节点,可以考虑使用lxml.etree.iterparse()
相反,这将避免尝试在内存中构建完整的DOM树,否则将比构建树并使用XPath迭代它更有效。 (想想SAX,但没有疯狂和痛苦的API)。
与iterparse
实施看起来是这样的:
def get_cars(infile):
in_car = False
current_car = {}
for (event, element) in lxml.etree.iterparse(infile, events=('start', 'end')):
if event == 'start':
if element.tag == 'Car':
in_car = True
current_car = {}
continue
if not in_car: continue
if element.tag == 'Car':
yield current_car
continue
current_car[element.tag] = element.text
for car in get_cars(infile = cStringIO.StringIO('''<root><Car><Color>Blue</Color><Make>Chevy</Make><Model/></Car></root>''')):
print car
...这是更多的代码,但(如果我们不使用StringIO的的例子),它可以处理除了可以适应更大的文件记忆。
解决方案:使用try/except
块来捕捉关键错误。
错误只发生在第一位,因为他没有文字过滤掉元素。为什么要避开它,在过程中缩短代码? – 2012-03-08 15:58:17
@CharlesDuffy我认为OP有这样做的一些理由,也许他正在使用其他地方创建的数据结构。 – Marcin 2012-03-08 16:00:35
是的,但结构很好 - 这是他用来检索部分结构的过滤器,而这部分显然是他的代码。 – 2012-03-08 16:48:52
我捕捉到了异常:
try:
print parsedCarData[0]['Model']
except KeyError:
print 'No model specified'
异常在Python是不是在同一意义非凡在其他语言中,在那里它们被更严格地链接到错误条件。相反,它们通常是设计中正常使用模块的一部分。例如,一个迭代器引发StopIteration
来表示它已经达到迭代的结束。
编辑:如果你确定只有这个项目可以是空的@CharlesDuffy有它的权利,因为使用get()
可能更好。但总的来说,我会考虑使用异常来轻松处理各种异常输出。
使用'parsedCarModel [0] .get('Model')'来避免异常(在未找到的情况下返回'None')比提升和处理异常更短更快......尽管我认为这是当从XPath查询中移除不必要的限制时,很愚蠢的做法首先会导致这个问题。 – 2012-03-08 15:59:47
@CharlesDuffy:没错,但我认为这种方法有很多优点。我通常使用try/except块来包装行,我在其中几个关于输入的几个假设。在这种情况下,使用异常似乎比改变每一行更自然。另外,通常你必须用无论如何处理None。 – 2012-03-08 16:08:13
现在我正在做一个'element = etree.parse(xmlfile)'。 iterparse如何改变我现有的代码库? – lodkkx 2012-03-08 15:39:50
@lodkkx使用iterparse如下所示:lxml.etree.iterparse(xmlfile):...中的for(event_type,element):决定每个元素依次执行什么操作(通常是通过检查其标记)。 – 2012-03-08 15:46:52