tags:

views:

37

answers:

3

I have the following input

<row test="1" />

and want to generate the following output when using XmlTextWriter.

<?xml version="1.0"?>
<root xmlns="urn:default">
  <row test="1" />
</root>

According to the documentation for InnerXml (MSDN), the following code should work correctly.

var outputdoc = new XmlDocument();
outputdoc.AppendChild(outputdoc.CreateXmlDeclaration("1.0", string.Empty, string.Empty));
outputdoc.AppendChild(outputdoc.CreateElement("root", "urn:default"));
outputdoc.DocumentElement.InnerXml = "<row test=\"1\" />";

var writer = new XmlTextWriter(filename, Encoding.UTF8) { Formatting = Formatting.Indented, Indentation = 1 };
outputdoc.WriteTo(writer);
writer.Close();

Instead, I get the following output:

<?xml version="1.0"?>
<root xmlns="urn:default">
  <row test="1" xmlns="" />
</root>

What do I need to do?

EDIT:

I didn't make the possible inputs clear enough. It was supposed to be an Xml fragment so it could be one element, more than one element with any number of children in either case. For example:

<row test="1" />

or

<row test="1" />
<row test="2" />

or

<row><test>1</test></row>

or

<row><test>1</test></row>
<row test="2" />
+2  A: 

Must you use System.Xml? If you were to use XElement, it would be trivial:

XElement root = new XElement(XName.Get("root", "urn:default"));
XElement child = XElement.Parse("<row test=\"1\" />");
root.Add(child);
child.Name = XName.Get("row", "urn:default");
Console.WriteLine(root.ToString());

Prints out:

<root xmlns="urn:default">
    <row test="1" />
</root>
Kirk Woll
System.Xml isn't absolutely necessary. Is there also a way to parse the following string "<row test=\"1\" /><row test=\"2\" />"?
somori
Yes, but since that's not technically valid XML (the fragment contains multiple root nodes), you'd have to do something hacky like surrounding your string with a containing element. i.e. "<elements><row test=\"1\" /> ... </elements>". Then once you parse that you can just grab the child nodes (and ignore the dummy parent element.)
Kirk Woll
+1  A: 

You could write it all out using the XmlTextWriter, although I would advise caution unless you are sure it is doing what you want with the default namespace.

using(var writer = new XmlTextWriter(filename, Encoding.UTF8) { Formatting = Formatting.Indented, Indentation = 1 }) {
    writer.WriteStartDocument();
    writer.WriteStartElement("row","urn:default");
    writer.WriteRaw("<row test=\"1\" />");
    writer.WriteEndElement();
    writer.WriteEndDocument();
}
Nick Jones
Thanks for that. It worked for the namespace manipulation. Unfortunately, this solution removes the pretty printing so it isn't going to work for me.
somori
+1  A: 

This is because you are manipulating XML inconsistently: first, you are building an element properly with an API that handles namespaces, but then you build an element with InnerXML...

<row test="2"/> 

How could any application know that this element is in the default namespace or in empty namespace? Like in XPath, empty namespace is assumed.

Then, you have a parent in some default namespace and a child in empty namespace. So, the namespace fixup mechanism adds a default namespace reset xmlns="".

How to avoid this ussing InnerXML?

outputdoc.DocumentElement.InnerXml = "<row test=\"1\" xmlns=\"urn:default\" />"; 

Edit: About @somori comment, from this http://msdn.microsoft.com/en-us/library/system.xml.xmlelement.innerxml.aspx

Setting this property replaces the children of the node with the parsed contents of the given string. The parsing is done in the current namespace context.

This property is a Microsoft extension to the Document Object Model (DOM).

Extension of DOM means non standar...

Alejandro
According to the documentation, setting InnerXml to an XML fragment without a namespace defintion should put that fragment within the default namespace. My input xml can be pretty much anything but will all be within the same namespace, which I then have to force into the correct parent element with the correct namespace.
somori
@somori: According to what documentation? Check my edit.
Alejandro
As linked in question - http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.innerxml%28v=VS.85%29.aspx - this describes a different situation. I have realised that there isn't much clarity in this description and it needs better testing.
somori
@somori: Inconsisten documentation seems to be one of the problems for non standar extensions...
Alejandro