2013-08-20 53 views
7

我正在编写一个Python脚本来更新Visual Studio项目文件。他们是这样的:无法使用默认命名空间编写XML文件

<?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文件,因此忽略它不是可选的。

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

+0

看起来这是一个已知的错误。请参阅http://bugs.python.org/issue17088 – WombatPM

回答

22

这是一个重复,以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标签。

3

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

+1虽然它看起来像'lxml.etree'不适用于Windows的Python,所以我会接受WombatPM的回答 – Andomar

+0

@ WombatPM的答案也很棒,但lxml可用为windows。你可以使用pip,easy_install和(我认为)活动状态的pypm ......或者只是从(pypi)[https://pypi.python.org/pypi/lxml/3.2.3]抓取它。 – tdelaney

+0

我也使用了lxml。两者都很好。 – WombatPM

0

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

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

只是在我的文件解析不起作用。

您需要找到正在使用的xml文件的特定命名空间。要做到这一点,我打印出来的元件,它给了我的命名空间使用和标签名ET树节点的标签,复制该命名空间为:

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

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