Python:忽略xml.etree.ElementTree中的命名空间?

时间:2015-12-04 06:55:59

标签: python xml elementtree

如何告诉ElementTree忽略XML文件中的命名空间?

例如,我更愿意查询modelVersion(如语句1中)而不是{http://maven.apache.org/POM/4.0.0}modelVersion(如语句2中所示)。

pom="""
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
</project>
"""

from xml.etree import ElementTree
ElementTree.register_namespace("","http://maven.apache.org/POM/4.0.0")
root = ElementTree.fromstring(pom)

print 1,root.findall('modelVersion')
print 2,root.findall('{http://maven.apache.org/POM/4.0.0}modelVersion')

1 []
2 [<Element '{http://maven.apache.org/POM/4.0.0}modelVersion' at 0x1006bff10>]

4 个答案:

答案 0 :(得分:0)

似乎没有直接的途径,因此我只是简单地包裹查找呼叫,例如

from xml.etree import ElementTree as ET

POM = """
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
</project>
"""

NSPS = {'foo' : "http://maven.apache.org/POM/4.0.0"}

# sic!
def findall(node, tag):
    return node.findall('foo:' + tag, NSPS) 

root = ET.fromstring(POM)
print(map(ET.tostring, findall(root, 'modelVersion')))

输出:

['<ns0:modelVersion xmlns:ns0="http://maven.apache.org/POM/4.0.0">4.0.0</ns0:modelVersion>\n']

答案 1 :(得分:0)

这就是我现在正在做的事情,这让我非常自信有更好的方式。

$ cat pom.xml |
   tr '\n' ' ' |
   sed 's/<project [^>]*>/<project>/' |
   myprogram |
   sed 's/<project>/<project xmlns="http:\/\/maven.apache.org\/POM\/4.0.0" xmlns:xsi="http:\/\/www.w3.org\/2001\/XMLSchema-instance" xsi:schemaLocation="http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/maven-v4_0_0.xsd">/'

答案 2 :(得分:0)

不是忽略,另一种方法是删除树中的命名空间,因此不需要忽略&#39;因为它们不存在 - 请参阅nonagon对此问题的回答(以及我对该问题的扩展以包括属性上的命名空间):Python ElementTree module: How to ignore the namespace of XML files to locate matching element when using the method "find", "findall"

答案 3 :(得分:0)

这是不使用shell的等效解决方案。基本理念:

  • <project junk...>翻译为<project>
  • 执行“干净”处理而不用担心命名空间
  • <project>翻译回<project junk...>

使用新代码:

pom="""
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
</project>
"""
short_project="""<project>"""
long_project="""<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">"""

import re,sys
from xml.etree import ElementTree

# eliminate namespace specs
pom=re.compile('<project [^>]*>').sub(short_project,pom)

root = ElementTree.fromstring(pom)
ElementTree.dump(root)
print 1,root.findall('modelVersion')
print 2,root.findall('{http://maven.apache.org/POM/4.0.0}modelVersion')
mv=root.findall('modelVersion')

# restore the namespace specs
pom=ElementTree.tostring(root)
pom=re.compile(short_project).sub(long_project,pom)