繁体   English   中英

使用名称空间解析XML

[英]Parsing XML with namespace

有了这个XML

<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
    <subject>Reference rates</subject>
    <Sender>
        <name>European Central Bank</name>
    </Sender>
    <Cube>
        <Cube time='2013-12-20'>
            <Cube currency='USD' rate='1.3655'/>
            <Cube currency='JPY' rate='142.66'/>
        </Cube>
    </Cube>
</Envelope>

我可以获得这样的内部Cube标签

from xml.etree.ElementTree import ElementTree

t = ElementTree()
t.parse('eurofxref-daily.xml')
day = t.find('Cube/Cube')
print 'Day:', day.attrib['time']
for currency in day:
    print currency.items()

Day: 2013-12-20
[('currency', 'USD'), ('rate', '1.3655')]
[('currency', 'JPY'), ('rate', '142.66')]

问题是上述XML是已定义名称空间的原始文件的清理版本

<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <gesmes:subject>Reference rates</gesmes:subject>
    <gesmes:Sender>
        <gesmes:name>European Central Bank</gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time='2013-12-20'>
            <Cube currency='USD' rate='1.3655'/>
            <Cube currency='JPY' rate='142.66'/>
        </Cube>
    </Cube>
</gesmes:Envelope>

当我尝试获取第一个Cube标签时,我得到了None

t = ElementTree()
t.parse('eurofxref-daily.xml')
print t.find('Cube')

None

根标记包括名称空间

root = t.getroot()
print 'root.tag:', root.tag

root.tag: {http://www.gesmes.org/xml/2002-08-01}Envelope

它的孩子们也

for e in root.getchildren():
    print 'e.tag:', e.tag

e.tag: {http://www.gesmes.org/xml/2002-08-01}subject
e.tag: {http://www.gesmes.org/xml/2002-08-01}Sender
e.tag: {http://www.ecb.int/vocabulary/2002-08-01/eurofxref}Cube

如果我在标签中包含名称空间,则可以获得Cube标签

day = t.find('{http://www.ecb.int/vocabulary/2002-08-01/eurofxref}Cube/{http://www.ecb.int/vocabulary/2002-08-01/eurofxref}Cube')
print 'Day: ', day.attrib['time']

Day:  2013-12-20

但这真的很丑。 除了在处理或进行字符串处理之前清理文件外,还有一种优雅的方式来处理它吗?

除了在查询文本中包含整个名称空间URI外,还有一种更优雅的方法。 对于不支持ElementTree.find上的namespaces参数的python版本, lxml提供了缺少的功能,并且与xml.etree “基本兼容”:

from lxml.etree import ElementTree

t = ElementTree()
t.parse('eurofxref-daily.xml')
namespaces = { "exr": "http://www.ecb.int/vocabulary/2002-08-01/eurofxref" }
day = t.find('exr:Cube', namespaces)
print day

使用namespaces对象,您可以一次全部设置它,然后仅在查询中使用前缀。

这是输出:

$ python test.py
<Element '{http://www.ecb.int/vocabulary/2002-08-01/eurofxref}Cube' at 0x7fe0f95e3290>

如果发现前缀不雅观,则必须处理没有名称空间的文件。 或者,也许还有其他工具可以“欺骗”并在local-name()上进行匹配,即使名称空间有效,但我也不使用它们。

在python 2.7或python 3.3或更高版本中,您可以使用与上述相同的代码,但使用xml.etree而不是lxml因为它们已在这些版本中添加了对名称空间的支持。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM