C# - 将 XElement 数组追加到 XElement
C# - Append an XElement array to XElement
我有一个 c# 应用程序,我在一个名为 RevisionTree 的方法中对两个 xml 文件进行数据比较。我 return 来自此方法的元素列表 (XElement)。从 BuildXml 方法调用该方法并将列表保存为 tree。接下来我创建一个 xml root XElement。然后我遍历树中的每个元素并将指定的后代(状态、消息、日期)添加到 root 元素,其中每一个都是 XElement。所以我应该看到一个 xml 带有 root 的文档,然后是一个重复 xml 的列表。 但是,当我尝试将其保存到编写器时,出现以下错误。
错误
Exception thrown: 'System.InvalidOperationException' in System.Private.Xml.dll
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Private.Xml.dll
Token StartDocument in state Document would result in an invalid XML document.
代码
{
IEnumerable<XElement>
var tree = RevisionTree("C:\Users\Owner\source\repos\SvnCore\SvnCore\old_logs.xml", "C:\Users\Owner\source\repos\SvnCore\SvnCore\new_logs.xml");
using (XmlWriter writer = XmlWriter.Create("C:\Users\Owner\source\repos\SvnCore\SvnCore\Temp.xml", xmlSettings))
{
writer.WriteStartDocument();
var root = new XElement("root");
foreach (var node in tree)
{
root.Add(new XElement("id", node.FirstAttribute));
root.Add(node.Descendants("status").FirstOrDefault());
root.Add(node.Descendants("msg").FirstOrDefault());
root.Add(node.Descendants("date").FirstOrDefault());
}
root.Save(writer);
writer.WriteEndElement();
writer.WriteEndDocument();
}
return true;
}
XElement.Save
自行生成整个文档——您需要 XElement.WriteTo
,而后者不需要。所以要么(简化):
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
using (XmlWriter writer = XmlWriter.Create(sw)) {
var root = new XElement("root");
root.Add(new XElement("id", "1"));
root.Save(writer); // no DocumentStart, no ElementStart
}
<?xml version="1.0" encoding="utf-16"?><root><id>1</id></root>
或者(如果你想写多个元素,或者出于其他原因想自己控制文档节点):
using (XmlWriter writer = XmlWriter.Create(sw)) {
writer.WriteStartDocument();
writer.WriteStartElement("root");
var notRoot = new XElement("notRoot");
notRoot.Add(new XElement("id", "1"));
notRoot.WriteTo(writer);
notRoot.WriteTo(writer);
}
<?xml version="1.0" encoding="utf-16"?><root><notRoot><id>1</id></notRoot><notRoot><id>1</id></notRoot></root>
请注意,我省略了 End
调用,因为 XmlWriter
会隐式处理它。
如果你没有对 xmlSettings
做任何有趣的事情,整个事情就更简单了,因为 XElement.Save
有一个直接接受文件名的重载,所以你不需要XmlWriter
完全没有。
我有一个 c# 应用程序,我在一个名为 RevisionTree 的方法中对两个 xml 文件进行数据比较。我 return 来自此方法的元素列表 (XElement)。从 BuildXml 方法调用该方法并将列表保存为 tree。接下来我创建一个 xml root XElement。然后我遍历树中的每个元素并将指定的后代(状态、消息、日期)添加到 root 元素,其中每一个都是 XElement。所以我应该看到一个 xml 带有 root 的文档,然后是一个重复 xml 的列表。 但是,当我尝试将其保存到编写器时,出现以下错误。
错误
Exception thrown: 'System.InvalidOperationException' in System.Private.Xml.dll
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Private.Xml.dll
Token StartDocument in state Document would result in an invalid XML document.
代码
{
IEnumerable<XElement>
var tree = RevisionTree("C:\Users\Owner\source\repos\SvnCore\SvnCore\old_logs.xml", "C:\Users\Owner\source\repos\SvnCore\SvnCore\new_logs.xml");
using (XmlWriter writer = XmlWriter.Create("C:\Users\Owner\source\repos\SvnCore\SvnCore\Temp.xml", xmlSettings))
{
writer.WriteStartDocument();
var root = new XElement("root");
foreach (var node in tree)
{
root.Add(new XElement("id", node.FirstAttribute));
root.Add(node.Descendants("status").FirstOrDefault());
root.Add(node.Descendants("msg").FirstOrDefault());
root.Add(node.Descendants("date").FirstOrDefault());
}
root.Save(writer);
writer.WriteEndElement();
writer.WriteEndDocument();
}
return true;
}
XElement.Save
自行生成整个文档——您需要 XElement.WriteTo
,而后者不需要。所以要么(简化):
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
using (XmlWriter writer = XmlWriter.Create(sw)) {
var root = new XElement("root");
root.Add(new XElement("id", "1"));
root.Save(writer); // no DocumentStart, no ElementStart
}
<?xml version="1.0" encoding="utf-16"?><root><id>1</id></root>
或者(如果你想写多个元素,或者出于其他原因想自己控制文档节点):
using (XmlWriter writer = XmlWriter.Create(sw)) {
writer.WriteStartDocument();
writer.WriteStartElement("root");
var notRoot = new XElement("notRoot");
notRoot.Add(new XElement("id", "1"));
notRoot.WriteTo(writer);
notRoot.WriteTo(writer);
}
<?xml version="1.0" encoding="utf-16"?><root><notRoot><id>1</id></notRoot><notRoot><id>1</id></notRoot></root>
请注意,我省略了 End
调用,因为 XmlWriter
会隐式处理它。
如果你没有对 xmlSettings
做任何有趣的事情,整个事情就更简单了,因为 XElement.Save
有一个直接接受文件名的重载,所以你不需要XmlWriter
完全没有。