无法使用默认命名空间编写XML文件

时间:2013-08-20 15:17:27

标签: python xml elementtree

我正在编写一个Python脚本来更新Visual Studio项目文件。它们看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" 
      xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
      ...

以下代码读取并写入文件:

import xml.etree.ElementTree as ET

tree = ET.parse(projectFile)
root = tree.getroot()
tree.write(projectFile,
           xml_declaration = True,
           encoding = 'utf-8',
           method = 'xml',
           default_namespace = "http://schemas.microsoft.com/developer/msbuild/2003")

Python在最后一行抛出错误,说:

ValueError: cannot use non-qualified names with default_namespace option

这是令人惊讶的,因为我只是在阅读和写作,两者之间没有编辑。 Visual Studio拒绝加载没有默认命名空间的XML文件,因此省略它不是可选的。

为什么会出现此错误?建议或替代方案欢迎。

3 个答案:

答案 0 :(得分:28)

这与Saving XML files using ElementTree

重复

解决方案是在解析项目文件之前定义默认命名空间。

ET.register_namespace('',"http://schemas.microsoft.com/developer/msbuild/2003")

然后将您的文件写为

tree.write(projectFile,
           xml_declaration = True,
           encoding = 'utf-8',
           method = 'xml')

您已成功将文件往返。并且避免在任何地方创建ns0标记。

答案 1 :(得分:4)

我认为lxml在处理命名空间方面做得更好。它的目标是类似ElementTree的接口,但在下面使用xmllib2。

>>> import lxml.etree
>>> doc=lxml.etree.fromstring("""<?xml version="1.0" encoding="utf-8"?>
... <Project ToolsVersion="4.0" DefaultTargets="Build" 
...       xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...   <PropertyGroup>
...   </PropertyGroup>
... </Project>""")

>>> print lxml.etree.tostring(doc, xml_declaration=True, encoding='utf-8', method='xml', pretty_print=True)
<?xml version='1.0' encoding='utf-8'?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build">
  <PropertyGroup>
  </PropertyGroup>
</Project>

答案 2 :(得分:0)

这是我能找到的最接近我的问题的答案。把:

ET.register_namespace('',"http://schemas.microsoft.com/developer/msbuild/2003")

在解析我的文件之前不起作用。

您需要找到要加载的xml文件所使用的特定命名空间。为此,我打印出了ET树节点标签的元素,它给了我要使用的命名空间和标签名称,将该命名空间复制到:

ET.register_namespace('',"XXXXX YOUR NAMESPACEXXXXXX")

在开始解析文件之前,应该在写入时删除所有命名空间。