为什么xml.etree.ElementTree不支持命名空间URI大小写变更
我正在处理XML文件,但遇到了一个问题,就是同一个命名空间的URI(统一资源标识符)大小写不一致。有些XML的拥有者决定把URI都写成小写。如果我先用一种URI解析数据,然后再用另一种URI解析数据,解析器就找不到我的数据,尽管我已经更新了命名空间字典来匹配文档的URI。下面是一个例子:
from cStringIO import StringIO
import xml.etree.ElementTree as ET
DATA_lc = '''<?xml version="1.0" encoding="utf-8"?>
<container xmlns:roktatar="http://www.example.com/lower/case/bug">
<item>
<roktatar:author>Boby Mac Gallinger</roktatar:author>
</item>
</container>'''
DATA_UC = '''<?xml version="1.0" encoding="utf-8"?>
<container xmlns:roktatar="http://www.example.com/Lower/Case/Bug">
<item>
<roktatar:author>John-John Le Grandiosant</roktatar:author>
</item>
</container>'''
tree = ET.parse(StringIO(DATA_lc))
root = tree.getroot()
ns = {'roktatar': 'http://www.example.com/lower/case/bug'}
for item in root.iter('item'):
print item.find('roktatar:author', namespaces=ns).text.strip()
tree = ET.parse(StringIO(DATA_UC))
root = tree.getroot()
ns = {'roktatar': 'http://www.example.com/Lower/Case/Bug'}
for item in root.iter('item'):
print item.find('roktatar:author', namespaces=ns).text.strip()
如果每个解析块单独处理,数据就能正确收集,但如果它们放在一起,第二个解析总是失败。我是不是需要在处理不同文档之间重置或清理解析器?这算不算一个bug呢?
谢谢
1 个回答
2
ElementTree的搜索代码会解析你传给find()
和相关函数的参数,这些参数是XPath表达式,并且会把生成的函数结果进行缓存,以便下次使用。
比如,当你搜索roktatar:author
时,这个表达式会被缓存为搜索'{http://www.example.com/lower/case/bug}author'
,但是在你的第二个文档中,这个绑定发生了变化。
换句话说,ElementTree假设相同的命名空间前缀总是会映射到相同的命名空间URI。
解决这个问题的更好方法是使用一个不同的前缀,比如可以用roktatar_uc
来表示URL的大写版本:
ns = {'roktatar_uc': 'http://www.example.com/Lower/Case/Bug'}
for item in root.iter('item'):
print item.find('roktatar_uc:author', namespaces=ns).text.strip()
但如果这不是一个选项,你就需要清除缓存:
from xml.etree import ElementPath
ElementPath._cache.clear()