2008-10-22 40 views
1

這是交易。我有一個有很多記錄的XML文檔。類似這樣的:通過記錄驗證和提取XML記錄到數據庫中

print("<?xml version="1.0" encoding="utf-8" ?> 
     <Orders> 
     <Order> 
     <Phone>1254</Phone> 
     <City>City1</City> 
     <State>State</State> 
     </Order> 
     <Order> 
     <Phone>98764321</Phone> 
     <City>City2</City> 
     <State>State2</State> 
     </Order> 
    </Orders>"); 

還有一個XSD模式文件。我想從這個文件中提取數據並將這些記錄插入數據庫表中。首先我想驗證每個訂單記錄。例如,如果文件中有5個訂單,其中2個訂單未通過驗證,我想將通過驗證的3插入到數據庫中,並將其他2個存儲。在一個XML文件中可以存儲數千個記錄。這裏最好的辦法是什麼?驗證將如何進行,因爲我需要放棄失敗的記錄,只使用通過驗證的記錄。目前,我正在使用XmlReaderSettings來驗證XML文檔記錄。在插入數據庫之前,我應該將這些記錄提取到另一個XML文件或數據集或自定義對象中。我正在使用.Net 3.5。任何代碼或鏈接是受歡迎的。

回答

0

你有兩個選擇:

  1. XmlDataDocumentXmlDocument。這種方法的缺點是數據將被緩存在內存中,如果你有很多數據,這是不好的。另一方面,您可以使用DataSet獲得良好的內存查詢功能。 XmlDocument要求您使用XPath查詢來處理數據,而XmlDataDocument爲您提供更像DataSet功能的體驗。

  2. XmlReader。這是一種好的,快速的方法,因爲數據沒有被緩存;你一次一小段地閱讀它。您可以從一個元素移動到另一個元素,並在應用程序中查詢有關該元素的信息,以決定如何處理它。這確實意味着你在你的應用程序的內存中保存了你所在的樹級別,但是對於像你這樣的簡單XML文件結構來說,這應該非常簡單。

我推薦您的案例中的選項2。它應該在內存使用方面很好地擴展,並且應該爲處理文件提供最簡單的實現。

1

如果數據完全乾淨地映射到對象模型,可以嘗試使用xsd.exe從.xsd生成一些類,然後將這些類處理到您選擇的DAL中。問題是,如果數量很高(你提到了數千條記錄),你很有可能會有一個往返行程。

另一種選擇是將數據「按原樣」傳遞給數據庫,並使用SQL/XML處理TSQL中的數據 - 大概是接受xml參數(SQL Server 2005等)的存儲過程, 。

+0

SQL部分是可擴展的。 – scarpacci 2011-10-29 14:22:41

0

很大程度上取決於您的方案中「驗證」的含義。我假設,由於您使用的是.xsd,因此您已經驗證數據在語法上是正確的。 因此,驗證可能意味着您將調用其他服務或過程來確定訂單是否有效?

您可能想看看Sql Server Integration Services。 SSIS中的XML任務可以讓你執行諸如XPath查詢,合併,可能任何事情以及你需要處理該文檔的所有事情。您也可以將它用於模式文件的所有前期驗證。

Marc將這些數據傳遞給存儲過程的選項也可能適用於這種情況,但是SSIS(或者甚至DTS,但是您將放棄太多與XML相關的選項)將讓你可視化地編排所有這些工作。此外,它將使這些事情更容易地用完,因此您最終應該擁有更具可擴展性的解決方案。

0

通過驗證我的意思是驗證每個節點。至少有一個錯誤的節點需要插入到一個新的xml文檔中。基本上最後我應該有2個XML文件。一個包含成功的節點,另一個包含故障節點。任何方式,我可以做到這一點?我正在使用LINQ。

1

我同意你應該使用XmlReader的想法,但我想我會嘗試一些有點不同。

基本上,我首先驗證整個XDocument,然後如果有錯誤,我通過命令枚舉並根據需要將它們裝箱。這不太好,但也許會給你一些想法。

 XDocument doc = XDocument.Load("sample.xml"); 
     XmlSchemaSet schemas = new XmlSchemaSet(); 
     schemas.Add("", "sample.xsd"); 

     bool errors = false; 
     doc.Validate(schemas, (sender, e) => 
     { 
      errors = true; 
     }); 

     List<XElement> good = new List<XElement>(); 
     List<XElement> bad = new List<XElement>(); 
     var orders = doc.Descendants("Order"); 
     if (errors) 
     { 
      foreach (var order in orders) 
      { 
       errors = false; 
       order.Validate(order.GetSchemaInfo().SchemaElement, schemas, (sender, e) => 
       { 
        errors = true; 
       }); 

       if (errors) 
        bad.Add(order); 
       else 
        good.Add(order); 
      } 
     } 
     else 
     { 
      good = orders.ToList(); 
     } 

而不是lambda表達式,你可以使用一個普通的函數,但我只是把它扔在一起。此外,您可以構建兩個XDocument,而不是將訂單元素放入列表中。我相信這裏也有很多其他問題,但也許這會引發一些問題。

+0

+1用於驗證Schema並使用Linq/Lambda – scarpacci 2011-10-29 14:22:09