使用 XmlDocument 向元素添加命名空间的正确方法

Correct way to add a namespace to an element using XmlDocument

我必须修改传入的 SOAP XML 消息以将名称空间添加到其中一个元素,以便反序列化工作。但是,当我将 xmlns 属性添加到正确的元素时,当我尝试通过流将 xml 加载到 XmlWriter 时出现错误(我需要在 IClientMessageInspector 实现中这样做替换消息回复)。

The prefix '' cannot be redefined from '' to 'http://www.example.com' within the same start element tag.

我有一个解决方法,即在我修改属性后,我从它自己的外部 XML 重新加载整个 XML 文档。这出于某种原因有效,但让我觉得必须有一种 'correct' 方法来做到这一点。

这是一个演示问题和我当前解决方案的示例测试:

    [Test]    
    public void XmlNamespaceTest()
    {
        var originalXmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><TestElement><Child>thing</Child></TestElement>";
        var desiredXmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><TestElement xmlns=\"http://www.example.com\"><Child>thing</Child></TestElement>";

        var doc = new XmlDocument();
        doc.LoadXml(originalXmlString);
        Assert.That(originalXmlString, Is.EqualTo(doc.OuterXml));

        // Write this document via an XMLWriter
        var ms = new MemoryStream();
        var xmlWriter = XmlWriter.Create(ms);
        doc.WriteTo(xmlWriter);
        xmlWriter.Flush();

        ms.Position = 0;
        StreamReader sr = new StreamReader(ms);
        var originalXmlViaXmlWriter = sr.ReadToEnd();

        Assert.That(originalXmlString, Is.EqualTo(originalXmlViaXmlWriter));

        // Add the namespace to the element
        ((XmlElement)doc.GetElementsByTagName("TestElement").Item(0))?.SetAttribute("xmlns", "http://www.example.com");
        Assert.That(desiredXmlString, Is.EqualTo(doc.OuterXml));


        // Now attempt to write this modified xml via an XMLWriter
        ms.SetLength(0);
        xmlWriter = XmlWriter.Create(ms);

        //Uncomment line below to fix the error.
        //doc.LoadXml(doc.OuterXml);

        doc.WriteTo(xmlWriter);
        xmlWriter.Flush();

        ms.Position = 0;
        sr = new StreamReader(ms);
        var modifedXmlViaXmlWriter = sr.ReadToEnd();
        Assert.That(desiredXmlString, Is.EqualTo(modifedXmlViaXmlWriter));
    }

根据 this,您无法更改 XmlDocument 中的元素命名空间。这也是@LocEngineer 在他的评论中发现的。引用的文章提到,执行此操作的唯一方法是保存并重新加载 XmlDocument,这正是您正在做的。

如果您可以改用 XDoxument,这是可能的。请参阅 this 答案以获得解决方案。