让lxml.objectify忽略XML命名空间?

4

我需要处理一些长这样的XML:

<ns2:foobarResponse xmlns:ns2="http://api.example.com">
  <duration>206</duration>
  <artist>
    <tracks>...</tracks>
  </artist>
</ns2:foobarResponse>

我发现了lxml和它的objectify模块,它可以让你像使用字典一样以Python方式遍历XML文档。
问题是:每次尝试访问元素时,它都会使用虚假的XML命名空间。就像这样:
from lxml import objectify

tree = objectify.fromstring(xml)
print tree.artist
# ERROR: no such child: {http://api.example.com}artist

它试图使用父命名空间访问<artist>,但该标记未使用命名空间。

有任何想法如何解决这个问题吗?谢谢。


不行。你可以通过提供一个修补过的根节点开始来欺骗lxml,但是它会在</ns2:foobarResponse>上抛出XMLSyntaxError错误,因为ns2未定义。你最好找另一个XML解析器,它返回每个节点的“localname”,例如:foobarResponse - milahu
2个回答

7
根据lxml.objectify 文档,属性查找默认使用其父元素的命名空间。
您可能想要的工作方式是:
print tree["{}artist"]

QName语法如果您的子元素有非空命名空间(例如“{http://foo/}artist”),那么它将起作用,但不幸的是,当前的源代码将空命名空间视为命名空间,因此所有objectify的查找功能都会帮助替换为空命名空间,并且您将没有运气。这可能是一个错误(应该可以使用“{}artist”),或者是为lxml人员提出的增强请求。
目前,最好的做法可能是:
print tree.xpath("artist")

我不确定使用xpath会对性能产生多大的影响,但这肯定是可行的。


3

仅供参考:请注意,自lxml 2.3以来,此功能已按预期工作。

从lxml更改日志中:

" [...]

2.3 (2011-02-06) 增加的功能

  • 在查找子元素时,lxml.objectify将“{}tag”视为空名称空间,而不是父名称空间。

[...]"

实际应用中:

>>> xml = """<ns2:foobarResponse xmlns:ns2="http://api.example.com">
...   <duration>206</duration>
...   <artist>
...     <tracks>...</tracks>
...   </artist>
... </ns2:foobarResponse>"""
>>> tree = objectify.fromstring(xml)
>>> print tree['{}artist']
artist = None [ObjectifiedElement]
    tracks = '...' [StringElement]
>>>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接