使用LXML和Python解析空白XML标记

时间:2012-03-08 15:28:02

标签: python xml parsing xml-parsing

以格式解析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

我如何解析这个空白标签。

4 个答案:

答案 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块来捕获关键错误。