验证XDocument时捕获架构信息

时间:2011-10-22 10:38:21

标签: c# xml c#-4.0 xsd linq-to-xml

这与此问题类似C# Get schema information when validating xml

但是,我正在使用XDocument进行LINQ目的。

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

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

在我目前的方法中(我愿意改变),除了架构信息之外,我能够捕获所需的一切。

我尝试访问Validation事件处理程序的SourceSchemaObject参数中的ValidationEventArgs,但它始终为null。我也尝试了XElement的GetSchemaInfo,看起来也是空的。

我正在使用RegEx来识别我想要捕获的特定验证错误,并通过验证事件处理程序的sender参数从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上的RegEx识别特定的验证错误(这已经有效,我已经测试了我计划使用的模式)

  2. 从XDocument中获取与导致错误的特定XElement相关的属性值(例如原始CSV中的行号和列号)

  3. 获取架构信息(如果可用),以便可以将字段类型和限制添加到输出消息中。

1 个答案:

答案 0 :(得分:6)

对于将来阅读此问题的任何人,我设法解决了我的问题,尽管方式与我最初提出的方式略有不同。

我遇到的第一个问题是,ValidationEventArgs中的SchemaInfo和XElement的GetSchemaInfo扩展方法都是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
}

在验证回调之后,似乎没有将Schema信息添加到XObject,因此如果您尝试在验证回调的中间访问它,它将为null,但是如果您捕获该元素,那么访问如果在Validate方法完成后,它将不为null。

然而,这又开启了另一个问题。 SchemaInfo对象模型没有很好地记录,我无法解析它以找到我需要的东西。

在我提出原始问题后,我发现了question。接受的答案链接到一个非常好的blog帖子,该帖子分解了SchemaInfo对象模型。我花了一些工作来改进代码以适应我的目的,但是它很好地说明了如何为任何XmlReader元素获取SchemaInfo(我能够将其更改为使用XObject)。