<p>基于XML的解决方案是为ElementTree编写一个helper类,该类:</p>
<ul>
<li>在解析为ElementTree之前在<em>抓取XML声明行在写入</em>时,如果不同时写入编码属性(我检查了源代码),则无法写入XML声明行。</li>
<li>解析输入文件一次,获取根元素的命名空间。向ElementTree注册该命名空间,将空字符串作为前缀。完成后,使用ElementTree<em>再次使用该新设置分析源文件。</li>
</ul>
<p>它有一个主要缺点:</p>
<ul>
<li><strong>XML注释丢失。</strong>我了解到,对于这种情况,这是不可接受的(我最初认为输入数据没有任何注释,但事实证明它有)。</li>
</ul>
<p>我的助手类示例:</p>
<pre><code>from xml.etree import ElementTree as ET
import re
class ElementTreeHelper():
def __init__(self, xml_file_name):
xml_file = open(xml_file_name, "rb")
self.__parse_xml_declaration(xml_file)
self.element_tree = ET.parse(xml_file)
xml_file.seek(0)
root_tag_namespace = self.__root_tag_namespace(self.element_tree)
self.namespace = None
if root_tag_namespace is not None:
self.namespace = '{' + root_tag_namespace + '}'
# Register the root tag namespace as having an empty prefix, as
# this has to be done before parsing xml_file we re-parse.
ET.register_namespace('', root_tag_namespace)
self.element_tree = ET.parse(xml_file)
def find(self, xpath_query):
return self.element_tree.find(xpath_query)
def write(self, xml_file_name):
xml_file = open(xml_file_name, "wb")
if self.xml_declaration_line is not None:
xml_file.write(self.xml_declaration_line + '\n')
return self.element_tree.write(xml_file)
def __parse_xml_declaration(self, xml_file):
first_line = xml_file.readline().strip()
if first_line.startswith('<?xml') and first_line.endswith('?>'):
self.xml_declaration_line = first_line
else:
self.xml_declaration_line = None
xml_file.seek(0)
def __root_tag_namespace(self, element_tree):
namespace_search = re.search('^{(\S+)}', element_tree.getroot().tag)
if namespace_search is not None:
return namespace_search.group(1)
else:
return None
def __main():
el_tree_hlp = ElementTreeHelper('houses.xml')
dogs_tag = el_tree_hlp.element_tree.getroot().find(
'{ns}house/{ns}dogs'.format(
ns=el_tree_hlp.namespace))
one_dog_added = int(dogs_tag.text.strip()) + 1
dogs_tag.text = str(one_dog_added)
el_tree_hlp.write('hejsan.xml')
if __name__ == '__main__':
__main()
</code></pre>
<p>输出:</p>
<pre><code><?xml version="1.0"?>
<group xmlns="http://dogs.house.local">
<house>
<id>2821</id>
<dogs>3</dogs>
</house>
</group>
</code></pre>
<p>如果有人对此解决方案有改进,请毫不犹豫地获取代码并加以改进。</p>