带有xpath的python etree和带前缀的命名空间

时间:2014-11-18 10:25:37

标签: python xml-namespaces elementtree prefix

我无法找到信息,如何使用命名空间解析我的XML:

我有这个xml:

<par:Request xmlns:par="http://somewhere.net/actual">
  <par:actual>blabla</par:actual>
  <par:documentType>string</par:documentType>
</par:Request>

并试图解析它:

dom = ET.parse(u'C:\\filepath\\1.xml')
rootxml = dom.getroot()
for subtag in rootxml.xpath(u'//par:actual'):
    #do something
    print(subtag)

并且有例外,因为它不知道名称空间前缀。 有没有最好的方法来解决这个问题,计算该脚本将不知道它要解析的文件和标签将要搜索?

搜索网络和stackoverflow我发现,如果我要添加:

namespace = {u'par': u"http://somewhere.net/actual"}
for subtag in rootxml.xpath(u'//par:actual', namespaces=namespace):
    #do something
    print(subtag)

有效。完善。但我不知道我将解析哪个XML,并且我的脚本也不知道搜索标记(例如//par:actual)。所以,我需要找到以某种方式从XML中提取命名空间的方法。

我找到了很多方法,如何提取名称空间URI,例如:

print(rootxml.tag)
print(rootxml.xpath('namespace-uri(.)'))
print(rootxml.xpath('namespace-uri(/*)'))

但是我应该如何提取前缀来创建ElementTree想要的字典呢?我不想在xml体上使用正则表达式怪物来提取前缀,我相信必须存在支持的方式,不是吗?

也许有一些方法让我可以通过ETree命名空间从XML中提取为字典(就像ETree想要的那样!)而不用手动操作?

3 个答案:

答案 0 :(得分:2)

您不能依赖根元素上的名称空间声明:不能保证声明甚至会存在,或者文档将始终具有相同名称空间的相同前缀。 假设您要通过某种方式传递要搜索的标记(因为您说它不为您的脚本所知),您还应该提供一种传递命名空间映射的方法。或者使用James Clark表示法,例如{http://somewhere.net/actual}actualETXPath支持此语法,而“普通”xpath则不支持,但如果你不使用.findall(),你也可以使用其他方法不需要完整的xpath)

如果你根本不关心前缀,你也可以在xpath中使用local-name()函数,例如。 //*[local-name()="actual"](但你不会“真的”确定它是正确的“实际”)

答案 1 :(得分:1)

哦,我找到了。

我们这样做之后:

dom = ET.parse(u'C:\\filepath\\1.xml')
rootxml = dom.getroot()

对象rootxml包含字典nsmap,其中包含我想要的所有命名空间。

所以,我发现最简单的解决方案:

dom = ET.parse(u'C:\\filepath\\1.xml')
rootxml = dom.getroot()
nss = rootxml.nsmap
for subtag in rootxml.xpath(u'//par:actual', namespaces=nss):
    #do something
    print(subtag)

有效。

UPD:如果用户理解他使用的XML中的'par'是什么意思,那就有效。例如,在任何其他操作之前将假定的命名空间与现有命名空间进行比较。

尽管如此,我喜欢XPath的多种变体,它理解{...}实际,这就是我试图实现的目标。

答案 2 :(得分:1)

使用 Python 3.8.2 我发现这个问题有同样的问题。

这是我找到的解决方案,将命名空间放在 XPath 查询中。 (在 {} 之间)

ApplicationArea = BOD_IN_tree.find('.//ApplicationArea', ns)
if(ApplicationArea is None):
  ApplicationArea = BOD_IN_tree.find('.//{http://www.defaultNamespace.com/2}ApplicationArea', ns)

我搜索没有命名空间的元素,如果没有找到,则再次搜索。我无法控制入站文档,有些有命名空间,有些没有。

我希望这会有所帮助!

相关问题