Ark*_*ady 5 python prefix elementtree xml-namespaces
我找不到信息,如何使用命名空间解析我的 XML:
我有这个xml:
<par:Request xmlns:par="http://somewhere.net/actual">
<par:actual>blabla</par:actual>
<par:documentType>string</par:documentType>
</par:Request>
Run Code Online (Sandbox Code Playgroud)
并试图解析它:
dom = ET.parse(u'C:\\filepath\\1.xml')
rootxml = dom.getroot()
for subtag in rootxml.xpath(u'//par:actual'):
#do something
print(subtag)
Run Code Online (Sandbox Code Playgroud)
并且得到了异常,因为它不知道命名空间前缀。有没有最好的方法来解决这个问题,计算那个脚本不会知道它要解析的文件和标签要搜索的文件?
搜索网络和 stackoverflow 我发现,如果我会在那里添加:
namespace = {u'par': u"http://somewhere.net/actual"}
for subtag in rootxml.xpath(u'//par:actual', namespaces=namespace):
#do something
print(subtag)
Run Code Online (Sandbox Code Playgroud)
那个有效。完美的。但是我不知道我将解析哪个 XML,并且//par:actual我的脚本也不知道搜索标记(例如)。所以,我需要找到从 XML 中提取命名空间的方法。
找了很多方法,如何提取namespace URI,比如:
print(rootxml.tag)
print(rootxml.xpath('namespace-uri(.)'))
print(rootxml.xpath('namespace-uri(/*)'))
Run Code Online (Sandbox Code Playgroud)
但是我应该如何提取前缀来创建 ElementTree 想要的字典?我不想在 xml 正文上使用正则表达式怪物来提取前缀,我相信必须存在支持的方式,不是吗?
也许必须存在一些方法让我通过 ETree 命名空间从 XML 中提取作为字典(如 ETree 想要的!)而无需手动操作?
哦,我找到了。
在我们这样做之后:
dom = ET.parse(u'C:\\filepath\\1.xml')
rootxml = dom.getroot()
Run Code Online (Sandbox Code Playgroud)
对象 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)
Run Code Online (Sandbox Code Playgroud)
那个有效。
UPD:如果用户理解他所使用的 XML 中的“par”是什么意思,那就行了。例如,在任何其他操作之前将假定的命名空间与现有的命名空间进行比较。
尽管如此,我还是喜欢 XPath 的许多变体,它理解 {...}actual,这就是我试图实现的目标。
您不能依赖根元素上的命名空间声明:不能保证声明甚至会在那里,或者文档将始终具有相同命名空间的相同前缀。假设您将有某种方式传递您想要搜索的标签(因为您说您的脚本不知道它),您还应该提供一种传递命名空间映射的方式。或者使用 James Clark 表示法,例如{http://somewhere.net/actual}actual(ETXPath支持此语法,而“普通”xpath 不支持,但您也可以使用其他方法,例如.findall()如果您不需要完整的 xpath)
如果您根本不关心前缀,您也可以local-name()在 xpath 中使用该函数,例如。//*[local-name()="actual"](但你不会“真的”确定它是正确的“实际”)
| 归档时间: |
|
| 查看次数: |
6883 次 |
| 最近记录: |