Srini Srini - 1 month ago 7
C# Question

Get the XML record number based on the error line number C#

Below is my XML, I'm trying to get the record/row number based on the line number where the error occurred. For E.g if the validation error occurred at the value 0.53 which is line 6, i wanted to know its Record number which is 1 here, Adding

id="1", id="2"
..etc to
record
would be a good option , but as per my requirement the XML format cannot be changed.

<?xml version='1.0' encoding='utf-8'?>
<records>
<record>
<date>2016-02-01</date>
<id>3</id>
<value>0.53</value>
<unit>mtrs</unit>
</record>
<record>
<date>2016-02-01</date>
<id>4</id>
<value>0.13</value>
<unit>mtrs</unit>
</record>
<record>
<date>2016-02-01</date>
<id>7</id>
<value>0.13</value>
<unit>mtrs</unit>
</record>
</records>


Following is my code, I am getting the error line information using
IXmlLineInfo


//get the input file here
var httpRequest = HttpContext.Current.Request;

if (httpRequest.Files.Count > 0)
{
var postedFile = httpRequest.Files[0];

//sete the xsd schema path
string xsdPath = HttpContext.Current.Server.MapPath("~/XSD/MyFile.xsd");

//set the XSD schema here
var schema = new XmlSchemaSet();
schema.Add("", xsdPath);
var Message = "";

//validate the xml schema here
XDocument document = XDocument.Load(postedFile.InputStream, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo | LoadOptions.SetBaseUri);
//create a lists to add the error records
List<string> lstErrors = new List<string>();
document.Validate(schema, ValidationEventHandler);

//validate all the errors
document.Validate(schema, (sender, args) =>
{
IXmlLineInfo item = sender as IXmlLineInfo;
if (item != null && item.HasLineInfo())
{
//capture all the details needed here seperated by colons
Message = item.LineNumber + ";" +
(((System.Xml.Linq.XObject)item).Parent.Element("id")).Value + ";" +
((System.Xml.Linq.XElement)item).Name.LocalName + ";" +
args.Message + Environment.NewLine;
//add the error to a list
lstErrors.Add(Message);
}
});
}

Answer

Try the following approach.

After document loading, before validation, create the dictionary containing information about index and id for each record element.

XDocument document = XDocument.Load(...);

var dict = document.Root.Elements("record")
    .Select((r, index) => new { r, index })
    .ToDictionary(a => a.r, a => a.index);

Then use this dictionary in the validate event

if (item != null && item.HasLineInfo())
{
    Message = dict[((XObject)item).Parent] + ";" +
        item.LineNumber + ";" +
        (((XObject)item).Parent.Element("id")).Value + ";" +
        ((XElement)item).Name.LocalName + ";" +
        args.Message + Environment.NewLine;

    lstErrors.Add(Message);
}
Comments