2011-10-22 91 views
6

时,这是类似于此问题C# Get schema information when validating xml捕获架构信息验证的XDocument

不过,我与LINQ目的一个XDocument工作。

我正在读取/解析一组CSV文件并转换为XML,然后根据XSD模式验证XML。

我想捕捉与元素值相关的特定错误,生成更多用户友好的消息,并将它们返回给用户,以便可以更正输入数据。我希望在输出数据中包含的项目之一是某些模式信息(例如数字类型的可接受值的范围)。

在我目前的方法中(我愿意改变),除了模式信息之外,我能够捕捉到我需要的所有东西。

我试过访问SourceSchemaObjectValidationEventArgs验证事件处理程序的参数,但始终为空。我也尝试了XElement的GetSchemaInfo,而且看起来也是空的。

我正在使用RegEx来识别我想捕获的特定验证错误,并通过验证事件处理程序的发件人参数从XElement获取数据。我想过的模式转换到一个XDocument,抓住什么,我通过LINQ需要的,但在我看来,应该有一个更好的选择

这里是我当前的验证方法:

private List<String> this.validationWarnings; 
private XDocument xDoc; 
private XmlSchemaSet schemas = new XmlSchemaSet(); 

public List<String> Validate() 
{ 
    this.validationWarnings = new List<String>(); 

    // the schema is read elsewhere and added to the schema set 
    this.xDoc.Validate(this.schemas, new ValidationEventHandler(ValidationCallBack), true); 

    return validationWarnings 
} 

和这里的我的回调方法:

private void ValidationCallBack(object sender, ValidationEventArgs args) 
{   
    var element = sender as XElement; 

    if (element != null) 
    { 

     // this is a just a placeholder method where I will be able to extract the 
     // schema information and put together a user friendly message for specific 
     // validation errors  
     var message = FieldValidationMessage(element, args); 

     // if message is null, then the error is not one one I wish to capture for 
     // the user and is related to an invalid XML structure (such as missing 
     // elements or incorrect order). Therefore throw an exception 
     if (message == null) 
      throw new InvalidXmlFileStructureException(args.Message, args.Exception); 
     else 
      validationWarnings.Add(message); 

    } 
} 

在我的回调方法的var message = FieldValidationMessage(element, args);线只是一个占位符还不存在这种方法的目的是做三件事情:

  1. 通过args.Message使用正则表达式确定具体的验证错误(这个已经工作,我已经测试过,我打算使用模式)

  2. 抓住从涉及到具体的XElement的的XDocument导致该错误的属性值(如原始CSV中的行号和列号)

  3. 如果可用模式信息可用,则可将字段类型和限制添加到输出消息中。

回答

6

对于任何未来阅读此问题的人,尽管与原先建议的方式稍有不同,但我仍设法解决了我的问题。

我遇到的第一个问题是,XElement的ValidationEventArgs和GetSchemaInfo扩展方法中的SchemaInfo都是null。我解决了这个问题,就像我最初链接的问题一样。

List<XElement> errorElements = new List<XElement>(); 

serializedObject.Validate((sender, args) => 
{ 
    var exception = (args.Exception as XmlSchemaValidationException); 

    if (exception != null) 
    { 
     var element = (exception.SourceObject as XElement); 

     if (element != null) 
      errorElements.Add(element); 
    } 

}); 

foreach (var element in errorElements) 
{ 
    var si = element.GetSchemaInfo(); 

    // do something with SchemaInfo 
} 

这样看来,该模式的信息是不添加到X对象,直到确认后回调,因此,如果您尝试访问它在验证回调的中间,这将是空的,但如果您捕捉元素,然后在Validate方法完成后访问它,它不会为空。

但是,这又开辟了另一个问题。 SchemaInfo对象模型没有很好的文档记录,我无法解析出来找到我需要的东西。

我在问我原来的问题后发现这question。被接受的答案链接到一个非常棒的blog帖子,该帖子对SchemaInfo对象模型进行了细分。我花了一些工作来改进代码以适应我的目的,但它很好地阐释了如何为任何XmlReader元素(我可以更改为使用XObject)获取SchemaInfo。