开发者

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?

开发者 https://www.devze.com 2023-01-16 11:01 出处:网络
I have the following input <row test=\"1\" /> and want to generate the following output when using XmlTextWriter.

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...

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号