Reputation: 5808
I am trying to validate an XML file and display any errors to the user.
Simplified Example:
XML:
<MyApps>
<MyApp>
<Header>
<Name>Name 1</Name>
<Rate>4</Rate>
</Header>
<Players>
<Player>
<Name>Bert</Name>
<Age>22</Age>
</Player>
<Player>
<Name>Harry</Name>
<Age>12</Age>
</Player>
<Player>
<Name>George</Name>
<Age>16</Age>
</Player>
</Players>
</MyApp>
<MyApp>
<Header>
<Name>Name 2</Name>
<Rate>3</Rate>
</Header>
<Players>
<Player>
<Name>Fred</Name>
<Age>29</Age>
</Player>
<Player>
<Name>Bill</Name>
<Age>19</Age>
</Player>
<Player>
<Name>Garry</Name>
<Age>20</Age>
</Player>
</Players>
</MyApp>
</MyApps>
Validator:
public class XMLValidationMessage
{
public int LineNumber;
public int LinePosition;
public string Message;
public XmlSeverityType Severity;
}
public class XMLValidationResponse
{
/// <summary>
/// Result of the XML Validation.
/// </summary>
[Description("Result of the XML Validation")]
public bool IsXMLValid { get; set; }
/// <summary>
/// XML Validation Errors.
/// </summary>
[Description("XML Validation Errors")]
public List<XMLValidationMessage> ValidationErrors { get; set; }
public XMLValidationResponse()
{
ValidationErrors = new List<XMLValidationMessage>();
}
}
private static XMLValidationResponse response = new XMLValidationResponse();
public static XMLValidationResponse ValidateXML(string XMLFile, string XSDFile)
{
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.Add(null, XSDFile);
response.IsXMLValid = true;
Validate(XMLFile, schemaSet);
return response;
}
private static void Validate(String filename, XmlSchemaSet schemaSet)
{
XmlSchema compiledSchema = null;
foreach (XmlSchema schema in schemaSet.Schemas())
{
compiledSchema = schema;
}
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(compiledSchema);
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
settings.ValidationType = ValidationType.Schema;
//Create the schema validating reader.
XmlReader vreader = XmlReader.Create(filename, settings);
while (vreader.Read()) { }
//Close the reader.
vreader.Close();
}
private static void ValidationCallBack(object sender, ValidationEventArgs args)
{
response.IsXMLValid = false;
if (args.Severity == XmlSeverityType.Warning)
{
XMLValidationMessage xmlm = new XMLValidationMessage();
xmlm.Severity = XmlSeverityType.Warning;
xmlm.LineNumber = 0;
xmlm.LinePosition = 0;
xmlm.Message = "Matching schema not found. No validation occurred.";
response.ValidationErrors.Add(xmlm);
}
else
{
XMLValidationMessage xmlm = new XMLValidationMessage();
xmlm.Severity = XmlSeverityType.Error;
xmlm.LineNumber = args.Exception.LineNumber;
xmlm.LinePosition = args.Exception.LinePosition;
xmlm.Message = args.Message;
response.ValidationErrors.Add(xmlm);
}
}
If the XML fails validation I get a List of errors in the form of XMLValidationMessage
. This gives me a line number, Line position and message. However, there seems to be no way to link the error to the XML element that caused the error. After validation I deserialise the XML into a data class object then use this to populate a tree view. Ultimately what I want to do is highlight the branches of the treeview that failed validation. I am thinking that maybe I am going about this the wrong way?
Update - Example Error
ValidationErrors Count = 14 System.Collections.Generic.List<MyApp.Xml.XMLValidationMessage>
- [0] {MyApp.Xml.XMLValidationMessage} MyApp.Xml.XMLValidationMessage
LineNumber 89 int
LinePosition 127 int
Message "The 'http://www.myweb.co.uk/srm/mscc:Remarks' element is invalid - The value 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...' is invalid according to its datatype 'http://www.MyWeb.co.uk/srm/mscc:String50Type' - The actual length is greater than the MaxLength value." string
Severity Error System.Xml.Schema.XmlSeverityType
I get a collection of errors that are all valid errors. Not sure if the Schema would help that part is working fine. The trouble I am haiving is linking the error to the XML element causing the error.
Upvotes: 1
Views: 1354
Reputation: 1319
That data can be found in the sender argument in your ValidationCallbackMethod. I added a couple of lines to the else statement of the example ValidationCallbackMethod you posted.
private static void ValidationCallBack(object sender, ValidationEventArgs args)
{
response.IsXMLValid = false;
if (args.Severity == XmlSeverityType.Warning)
{
XMLValidationMessage xmlm = new XMLValidationMessage();
xmlm.Severity = XmlSeverityType.Warning;
xmlm.LineNumber = 0;
xmlm.LinePosition = 0;
xmlm.Message = "Matching schema not found. No validation occurred.";
response.ValidationErrors.Add(xmlm);
}
else
{
// this will give you the name of the schema element that failed validation
var schemaInfo = ((XmlReader)sender).SchemaInfo;
var elementThatFailedValidation = schemaInfo.SchemaElement.Name;
XMLValidationMessage xmlm = new XMLValidationMessage();
xmlm.Severity = XmlSeverityType.Error;
xmlm.LineNumber = args.Exception.LineNumber;
xmlm.LinePosition = args.Exception.LinePosition;
xmlm.Message = args.Message;
response.ValidationErrors.Add(xmlm);
}
}
Upvotes: 1