2013-08-20 76 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") 

你開始解析您的文件,那麼在這之前應該在編寫時刪除所有的命名空間。