2011-10-22 75 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。