I have a c# 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.