Search code examples
c#xmlxmltextwriter

Token StartElement in state Epilog would result in an invalid XML document


I am getting the error "Token StartElement in state Epilog would result in an invalid XML document." when i get the data from datatable and try to convery it to xml file .

Code :

DataTable dtTest = new DataTable();
dtTest.Columns.Add("Name");
dtTest.Columns.Add("NickName");
dtTest.Columns.Add("Code");
dtTest.Columns.Add("reference");

dtTest.Rows.Add("Yash", "POPs", "Vapi", "None1");
dtTest.Rows.Add("shilpa", "shilpa", "valsad", "None2");
dtTest.Rows.Add("Dinesh", "dinu", "pune", "None3");
dtTest.Rows.Add("rahul", "mady", "pardi", "None4");
XmlWriterSettings settings = new XmlWriterSettings();

StringWriter stringwriter = new StringWriter();

XmlTextWriter xmlTextWriter = new XmlTextWriter(stringwriter);
xmlTextWriter.Formatting = Formatting.Indented;
xmlTextWriter.WriteStartDocument();
foreach (var row in dtTest.AsEnumerable())
{
        xmlTextWriter.WriteStartElement("");
        xmlTextWriter.WriteAttributeString("orderid", row.Field<string>("Name"));
        xmlTextWriter.WriteElementString("type",  row.Field<string>("Name"));
        xmlTextWriter.WriteElementString("status", row.Field<string>("Name"));
        xmlTextWriter.WriteElementString("productno", row.Field<string>("Name"));
        xmlTextWriter.WriteEndElement();
}
XmlDocument docSave = new XmlDocument();
docSave.LoadXml(stringwriter.ToString());

What is the cause of this error, and how can it be fixed?


Solution

  • You have a few problems here:

    1. You are writing multiple root elements to your document, one for each call to xmlTextWriter.WriteStartElement(""). However, a well-formed XML document must have one and only one root element, so you need to wrap your row elements in some container element.

      (You might have been thinking that WriteStartDocument() would write the root element, but it does not. It just writes the XML declaration.)

    2. You are using XmlTextWriter but this class is deprecated. From the docs:

      Starting with the .NET Framework 2.0, we recommend that you create XmlWriter instances by using the XmlWriter.Create method and the XmlWriterSettings class to take advantage of new functionality.

      If you switch to XmlWriter you will get clearer error messages and better error checking.

    3. You are trying to write elements with no name:

      xmlTextWriter.WriteStartElement("");
      

      This would result in malformed XML. XmlTextWriter seems not to check for this, but XmlWriter does.

    Putting all of the above together, your code can be modified as follows:

    var stringwriter = new StringWriter();
    using (var xmlWriter = XmlWriter.Create(stringwriter, new XmlWriterSettings {  Indent = true }))
    {
        xmlWriter.WriteStartDocument();
        xmlWriter.WriteStartElement("Root");
        foreach (var row in dtTest.AsEnumerable())
        {
            xmlWriter.WriteStartElement("Row");
            xmlWriter.WriteAttributeString("orderid", row.Field<string>("Name"));
            xmlWriter.WriteElementString("type",  row.Field<string>("Name"));
            xmlWriter.WriteElementString("status", row.Field<string>("Name"));
            xmlWriter.WriteElementString("productno", row.Field<string>("Name"));
            xmlWriter.WriteEndElement();
        }
        xmlWriter.WriteEndElement();
    }
    var xml = stringwriter.ToString();
    

    Demo fiddle here.