我使用 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
。你能告诉我正确的方法吗?
一些注意事项:
XmlDocumentFragment
这样做,但结果完全相同我没有看到像这样混合 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());