XmlNode.InnerXml属性 - 省略xmlns属性

时间:2014-06-06 12:36:30

标签: c# .net xml xml-namespaces xmldocument

我有一些代码来替换XML文档的根节点名称,同时保留其名称空间。

XmlDocument doc = new XmlDocument();
Stream inStream = inmsg.BodyPart.GetOriginalDataStream();
doc.Load(inStream);

XmlNode root = doc.DocumentElement;
XmlNode replacement = doc.SelectSingleNode("/*/*[1]");

XmlNode newRoot = doc.CreateElement(replacement.Name);
XmlAttribute xmlns = (XmlAttribute)root.Attributes["xmlns"].Clone();
newRoot.Attributes.Append(xmlns);
newRoot.InnerXml = root.InnerXml; //the problem is here!

doc.ReplaceChild(newRoot, root);

使用如下所示的文档:

<OLD_ROOT xmlns="http://my.xml.namespace">
    <NEW_ROOT>

结果是:

<NEW_ROOT xmlns="http://my.xml.namespace">
     <NEW_ROOT xmlns="http://my.xml.namespace">

第二个xmlns是因为InnerXml属性显然将其设置在其内容的第一个节点上!我可以做些什么来规避这一点,而不必在事后删除它?

之后无法将其删除:

尝试使用以下代码

XmlNode first_node = doc.SelectSingleNode("/*/*[1]");
XmlAttribute excess_xmlns = first_node.Attributes["xmlns"];
first_node.Attributes.Remove(excess_xmlns);

但这不起作用,因为xmlns显然不存在于该节点上的属性!

1 个答案:

答案 0 :(得分:5)

两个变化:

  1. 在创建xmlns之后,不要添加newRoot属性,而是将命名空间指定为doc.CreateElement调用中的第二个参数。这可确保正确设置NamespaceURI属性。
  2. 使用InnerXml一次移动一个子节点,而不是复制xmlns(导致冗余AppendChild属性)。无论如何,这可能会更有效率。
  3. 因此:

    XmlNode root = doc.DocumentElement;
    XmlNode replacement = doc.SelectSingleNode("/*/*[1]");
    
    XmlNode newRoot = doc.CreateElement(replacement.Name, replacement.NamespaceURI);
    while (root.ChildNodes.Count > 0)
        newRoot.AppendChild(root.FirstChild);
    
    doc.ReplaceChild(newRoot, root);