使用 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 答案以获得解决方案。
我必须修改传入的 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 答案以获得解决方案。