以格式解析XML文档时:
<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
我如何解析这个空白标签。
答案 0 :(得分:3)
你正在放入一个[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作为示例)它可以处理比内存中更大的文件。
答案 1 :(得分:1)
我不知道在lxml中是否有更好的解决方案,但您可以使用.get()
:
print parsedCarData[0].get('Model', '')
答案 2 :(得分:0)
我会抓住异常:
try:
print parsedCarData[0]['Model']
except KeyError:
print 'No model specified'
Python中的异常与其他语言在同一意义上并不例外,因为它们与错误条件更严格地联系在一起。相反,它们通常是设计中模块正常使用的一部分。例如,迭代器引发StopIteration
以表示它已经到达迭代的末尾。
编辑:如果您确定只有这个项目可以为空@CharlesDuffy说得对,使用get()
可能更好。但总的来说,我会考虑使用例外来轻松处理各种异常输出。
答案 3 :(得分:-1)
解决方案:使用try/except
块来捕获关键错误。