使用 C# 在现有文档中插入 XML 字符串会破坏一切

问题描述 投票:0回答:1

我使用 C# 和

System.Xml
类来操作现有的 XML 文档。

特别是,我需要将字符串形式的 XML 片段插入文档中的特定节点内。

为此,我创建一个新元素,然后在其

InnerXml
属性中设置 XML 字符串,如下所示:

using System.Xml;

string nsUri = "http://myorg/myns";
string baseDocument = @$"<?xml version=""1.0"" encoding=""utf-16""?><Root xmlns=""{nsUri}""></Root>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(baseDocument);
var nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace("default", nsUri);

var target = doc.CreateElement("Target", nsUri);
target.InnerXml= @"
    <Sub1>This is a subnode</Sub1>
    <Sub2>Here is another subnode</Sub2>
";
doc.DocumentElement.AppendChild(target);

doc.Save(@"C:\text.xml");

查看输出,结果如下:

<?xml version="1.0" encoding="utf-16"?>
<Root xmlns="http://myorg/myns">
  <Target>
    <Sub1 xmlns="">This is a subnode</Sub1>
    <Sub2 xmlns="">Here is another subnode</Sub2>
</Target>
</Root>

如您所见,存在一个问题:我插入的 XML 字符串内的每个子节点都被分配了一个空的 xmlns 属性:

xmlns=""

这本身已经是一个问题,但更糟糕的问题是,这样做之后文档似乎处于不一致的状态,进一步的操作会产生奇怪的结果。例如,如果这样做后我这样做:

var sub1 = target.SelectSingleNode("default:Sub1", nsm);

那么

sub1
就是
null

所以,显然这不是正确的方法,当我重新分配时就会出现问题

InnerXml
。你能告诉我正确的方法吗?

一些注意事项:

  • 我知道我可以一一创建元素和属性,而不是仅仅将 XML 字符串转储到 InnerXml 中,但是我需要插入的 XML 片段非常长,在代码中手动重新创建它们是荒谬的。
  • 我尝试用
    XmlDocumentFragment
    这样做,但结果完全相同
c# .net xml .net-6.0 xmldocument
1个回答
0
投票

我没有看到像这样混合 DOM 和 XML 文本的真正简单的方法,但是下拉并使用 XmlReader,您可以完成它。还切换到 XDocument、EG

using System.Xml;
using System.Xml.Linq;

XNamespace ns = "http://myorg/myns";
string baseDocument = @$"<?xml version=""1.0"" encoding=""utf-16""?><Root xmlns=""{ns.ToString()}""></Root>";

XDocument doc = XDocument.Parse(baseDocument);

var target = new XElement(ns + "Target");

var fragment = @"
    <Sub1>This is a subnode</Sub1>
    <Sub2>Here is another subnode</Sub2>
";
var settings = new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment };
XmlReader reader = XmlReader.Create(new StringReader(fragment), settings);

while (reader.Read())
{
    while (reader.NodeType != XmlNodeType.Element)
    {
        if (!reader.Read()) break;
    }
    if (reader.EOF) break;
    var sr = reader.ReadSubtree(); 
    XElement subNode = XElement.Load(sr);
    subNode.Name = ns + subNode.Name.LocalName;
    target.Add(subNode);
}
doc.Root.Add(target);
Console.WriteLine(doc.ToString());
© www.soinside.com 2019 - 2024. All rights reserved.