Creating XML Elements without namespace declarations

You need to specify the XML namespace for all elements you add to the DOM:

XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");

XmlElement root = doc.DocumentElement;
XmlNode refNode = root.SelectSingleNode("x:Project", ns);

XmlElement newElement = doc.CreateElement(
    "PropertyGroup",
    "http://schemas.microsoft.com/developer/msbuild/2003");
var value = newElement.AppendChild(doc.CreateElement(
    "value",
    "http://schemas.microsoft.com/developer/msbuild/2003"));
value.AppendChild(doc.CreateTextNode("test"));

root.InsertAfter(newElement, refNode);

If you don't do so for any element (or if you use InnerXml like that), that element will get the dreaded empty namespace.


To avoid extra xmlns="" attribute in newly created elements you can pass root namespace as an argument:

 $child = $doc.CreateElement("value", $doc.DocumentElement.NamespaceURI);
 $res = $doc.PropertyGroup.AppendChild($child); # res here to avoid extra output

which will result in

<PropertyGroup>
    <value></value>
</PropertyGroup>

The reason this is happening is that you've defined the default namespace for the document to be "http://schemas.microsoft.com/developer/msbuild/2003" by having the namespace definition on the root node:

xmlns="http://schemas.microsoft.com/developer/msbuild/2003"

You then proceed to add an element which is in no namespace (the 'null' namespace) to the document. This has to be qualified with

xmlns=""

because if it wasn't it would mean that the new element was in the previously mentioned Microsoft namespace - which it isn't (or rather - which you haven't asked it to be).

So either:

  • you actually want the new element to be in the Microsoft namespace - in which case you need to say so. The easiest way is to use createElement and supply the namespace, although you can probably state it explicitly with an xmlns attribute on your InnerXml (which is not a particularly nice way of adding nodes).

  • You really do want this element in the null namespace, in which case you are probably better of qualifying all the other nodes that are not in the null namespace with a namespace prefix.

I suspect you want the former.

A quick overview on namespaces can be found here.

Tags:

C#

Xml