I'm writing a Python script to update Visual Studio project files. They look like this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
...
The following code reads and then writes the file:
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 throws an error at the last line, saying:
ValueError: cannot use non-qualified names with default_namespace option
This is surprising since I'm just reading and writing, with no editing in between. Visual Studio refuses to load XML files without a default namespace, so omitting it is not optional.
Why does this error occur? Suggestions or alternatives welcome.
You can change the default namespace within a particular element by adding an xmlns attribute to the element. Example 4-4 is an XML document that initially sets the default namespace to http://www.w3.org/1999/xhtml for all the XHTML elements. This namespace declaration applies within most of the document.
When you use multiple namespaces in an XML document, you can define one namespace as the default namespace to create a cleaner looking document. The default namespace is declared in the root element and applies to all unqualified elements in the document. Default namespaces apply to elements only, not to attributes.
No namespace exists when there is no default namespace in scope. A {default namespace} is one that is declared explicitly using xmlns.
A default namespace is a namespace that does not include a prefix. The default prefix is applied to all the elements that do not include a prefix and is unique for different XMLports. For example, the following string specifies a namespace: urn:microsoft-dynamics-nav/xmlports/x100 , where 100 is the ID of the XMLport.
This is a duplicate to Saving XML files using ElementTree
The solution is to define your default namespace BEFORE parsing the project file.
ET.register_namespace('',"http://schemas.microsoft.com/developer/msbuild/2003")
Then write out your file as
tree.write(projectFile,
xml_declaration = True,
encoding = 'utf-8',
method = 'xml')
You have successfully round-tripped your file. And avoided the creation of ns0 tags everywhere.
I think that lxml does a better job handling namespaces. It aims for an ElementTree-like interface but uses xmllib2 underneath.
>>> 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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With