How do I parse an xml fragment into nodes and append them to a node with a specified default namespace so that they are a part of that namespace?
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 cle开发者_运维知识库ar 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" />
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>
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();
}
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...
精彩评论