验证XML并显示失败的内容

时间:2014-01-14 13:32:12

标签: c# xml validation xml-serialization xml-validation

我正在尝试验证XML文件并向用户显示任何错误。

简化示例:

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>

验证

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);
        }

    }

如果XML验证失败,我会以XMLValidationMessage的形式获得错误列表。这给了我一个行号,行位置和消息。但是,似乎没有办法将错误链接到导致错误的XML元素。验证后,我将XML反序列化为数据类对象,然后使用它来填充树视图。最终我要做的是突出验证失败的树视图的分支。我在想,也许我会以错误的方式解决这个问题?

更新 - 示例错误

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

我得到的错误集合都是有效的错误。不确定Schema是否有助于该部分正常工作。我正在讨厌的麻烦是将错误链接到导致错误的XML元素。

1 个答案:

答案 0 :(得分:1)

可以在ValidationCallbackMethod中的sender参数中找到该数据。我在你发布的ValidationCallbackMethod示例的else语句中添加了几行代码。

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);
    }

}