2012-03-02 84 views
4

我有一系列來自亞馬遜顯示訂單報告的複雜XML文件。亞馬遜市場XML與LINQ解析

一個XML片斷是如下:

<Order> 
    <AmazonOrderID>000-1111111-2222222</AmazonOrderID> 
    <MerchantOrderID>111-3333333-4444444</MerchantOrderID> 
    <PurchaseDate>2012-03-02T13:28:53+00:00</PurchaseDate> 
    <LastUpdatedDate>2012-03-02T13:29:05+00:00</LastUpdatedDate> 
    <OrderStatus>Pending</OrderStatus> 
    <SalesChannel>Amazon.com</SalesChannel> 
    <URL>http://www.amazon.com</URL> 
    <FulfillmentData> 
    <FulfillmentChannel>Amazon</FulfillmentChannel> 
    <ShipServiceLevel>Standard</ShipServiceLevel> 
    <Address> 
     <City>Beverly Hills</City> 
     <State>CA</State> 
     <PostalCode>90210-1234</PostalCode> 
     <Country>US</Country> 
    </Address> 
    </FulfillmentData> 
    <OrderItem> 
    <ASIN>AmazonASIN </ASIN> 
    <SKU> Internal-SKU</SKU> 
    <ItemStatus>Pending</ItemStatus> 
    <ProductName> This is the name of the product </ProductName> 
    <Quantity>1</Quantity> 
    <ItemPrice> 
     <Component> 
     <Type>Principal</Type> 
     <Amount currency="USD">19.99</Amount> 
     </Component> 
    </ItemPrice> 
    </OrderItem> 
</Order> 

我需要這個文件做的是提取XML文檔的各個部分,然後做一些事情與數據。

我遇到的問題有多個訂購商品。

以下代碼將正確抓取每個節點並將其放入列表項中,但我不確定如何將這些多個項目與C#中的相同訂單號關聯起來。

C#片段:

List<string> getNodes(string path, string nodeName) { 

    List<string> nodes = new List<string>(); 

    XDocument xmlDoc = XDocument.Load(path); //Create the XML document type 

    foreach (var el in xmlDoc.Descendants(nodeName)) { 
      //for debugging 
      //nodes.Add(el.Name + " " + el.Value); 

      //for production 
      nodes.Add(el.Value); 
    } 
    return nodes; 
} //end getNodes 

的方法被稱爲像:

List<string> skuNodes = xml.getNodes(@"AmazonSalesOrders.xml", "SKU"); 

其中XML是實例化的類。

爲了進一步解釋複雜性:如果將每個節點放入自己的列表中,則列表的長度將保持不變,只提供一個項目。一旦訂購了多件商品,SKU,數量,價格等清單將變得更長,並防止輕鬆循環。

我確信有一個LINQ to XML語句可以完成我所需要的工作,但我沒有足夠的經驗可以用C#來破解它。

+++++++++++++++編輯+++++++++++++++++++

我想一些LINQ建議我在網上找到了。下面看起來很有希望,但返回的例外:

base {System.SystemException} = {"Object reference not set to an instance of an object."} 

代碼:

var query = from xEle in xmlDoc.Descendants(node) 
      where xEle.Element("AmazonOrderID").Value.ToString() == primaryKey 
      select new { 
        tag = xEle.Name.LocalName, 
        value = xEle.Value 
      }; 

我不清楚這是爲什麼發生的,節點的變量,和主鍵在運行時通過。

如果我設置斷點,我可以看到primaryKey正在正確傳遞,與節點相同;但是當我到達時:

Dictionary<string, string> ordersByID = new Dictionary<string, string>(); 

     foreach (var CurNode in query) { 
      ordersByID.Add(CurNode.tag, CurNode.value); 
     } 

我得到空引用錯誤,因爲它分析CurNode。

+0

請告訴我們您正在使用的是什麼amazon服務,以及您打算獲取此XML的URL是什麼? – Diego 2012-03-02 15:14:24

+2

URL和Web服務與問題無關,因爲問題不在於獲取XML文件本身,它將其解析爲將多個訂單項與相同的訂單ID相關聯。 – 2012-03-02 15:20:03

+0

'skuNodes.GroupBy(n => n.AmazonOrderID)'? – 2012-03-02 15:26:42

回答

2

您可以通過使用LINQ實現這一目標,你想,像這樣的財產以後應該工作,只是如果需要ITEMPRICE等加入更多的元素..:(其中ns是命名空間)

xmlDoc = XDocument.Parse(sr.ReadToEnd()); 

XNamespace ns = "w3.org/2001/XMLSchema-instance"; 

var query = from order in xmlDoc.Descendants(ns + "Order") 
      from orderItem in order.Elements(ns + "OrderItem") 
      select new 
      {   
       amazonOrdeID = order.Element(ns + "AmazonOrderID").Value, 
       merchantOrderID = order.Element(ns + "MerchantOrderID ").Value, 
       orderStatus = order.Element(ns + "OrderStatus ").Value, 
       asin = orderItem.Element(ns + "ASIN").Value, 
       quantity = orderItem.Element(ns + "quantity").Value 
      }; 

使用上述你可以在單行中將每個亞馬遜訂單所需的所有信息帶回...

+0

這是一個很大的幫助,感謝一羣保羅。下一個問題是關於命名空間 - 我目前沒有返回任何數據,並懷疑命名空間是問題。從XML文檔的命名空間是:xmlns:xsi =「http://www.w3.org/2001/XMLSchema-instance」xsi:noNamespaceSchemaLocation =「amzn-envelope.xsd」>。我添加了第一個沒有解析的命名空間,我如何將正確的命名空間添加到此代碼中? – 2012-03-05 14:12:44

+0

看到我上面的改變,命名空間將是「w3.org/2001/XMLSchema-instance」,讓我知道這是否爲你解決它。在我之前的代碼中,我有幾個錯字(captials),以及我已經修復的錯誤。 – Standage 2012-03-05 16:45:14

+0

我不認爲我的解決方案將工作TBH看着這個,你需要參考命名空間的第二部分.... – Standage 2012-03-05 17:24:31

0

我們之後決定使用其他方法,因此我沒有得到全面測試解決方案的機會,由於方向發生變化,我的評分完整。