简体   繁体   中英

C# - Append an XElement array to XElement

I have ac# application, where I'm doing a data compare of two xml files inside a method called RevisionTree . I return a list of elements(XElement) from this method. From the BuildXml method, call that method and save the list as tree . Next I create an xml root XElement. I then loop over each element from tree and add specified descendants (status, msg, date) to the root element, each one of these are XElement. So i should see an xml doument with root , then a list of repeating xml. However, when i try to save the to the writer i get the following error.

Error

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.

Code

    {
        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 produces an entire document on its own -- you need XElement.WriteTo , which does not. So either (simplified):

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>

or (if you wanted to write multiple elements, or for some other reason want to control the document node yourself):

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>

Note that I'm omitting the End calls, since the XmlWriter will take care of that implicitly.

If you aren't doing anything interesting with the xmlSettings , the whole thing is even simpler since XElement.Save has an overload that accepts a file name directly, so you don't need an XmlWriter at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM