【问题标题】:Cannot write XML file with default namespace [duplicate]无法使用默认命名空间写入 XML 文件 [重复]
【发布时间】:2013-08-22 17:25:24
【问题描述】:

我正在编写一个 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 文件,因此省略它不是可选的。

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

【问题讨论】:

标签: python xml elementtree


【解决方案1】:

这是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 标签。

【讨论】:

  • 这种方法有效。但是,find('mytag', ns)findall('mytag', ns) 方法失败(它们返回一个空的元素列表)。似乎它们需要一个 non-empty 命名空间名称。这很好,除非您想write() XML 文件,默认命名空间中的元素具有空的命名空间前缀。 (使用 Python 2.7。)
【解决方案2】:

我认为 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>

【讨论】:

  • +1 虽然看起来lxml.etree 不附带适用于 Windows 的 Python,所以我会接受 WombatPM 的回答
  • @WombatPM 的回答也很棒,但 lxml 可用于 Windows。您可以使用 pip、easy_install 和(我认为)Active State 的 pypm... 或者直接从 (pypi)[pypi.python.org/pypi/lxml/3.2.3].
  • 我也使用过 lxml。两者都很好。
【解决方案3】:

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-14
    相关资源
    最近更新 更多