【问题标题】:C# - Append an XElement array to XElementC# - 将 XElement 数组附加到 XElement
【发布时间】:2019-03-27 18:10:24
【问题描述】:

我有一个 c# 应用程序,我在一个名为 RevisionTree 的方法中对两个 xml 文件进行数据比较。我从这个方法返回一个元素列表(XElement)。从 BuildXml 方法调用该方法并将列表保存为 tree。接下来我创建一个 xml root XElement。然后我循环遍历树中的每个元素,并将指定的后代(状态、消息、日期)添加到 root 元素,其中每一个都是 XElement。所以我应该看到一个带有 root 的 xml doument,然后是一个重复 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; 
    }

【问题讨论】:

  • 试试root.WriteTo(writer)。 (或者,省略您手动编写文档/元素节点 - Save 应该已经处理它,这就是您收到错误的原因。)
  • @JeroenMostert,你是对的。请创建一个答案,(也许详细说明为什么我不应该使用 save ?),我会把它标记为正确的解决方案。

标签: c# .net xml linq xelement


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-28
    • 2011-01-27
    • 1970-01-01
    相关资源
    最近更新 更多