2012-03-02 55 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

我们之后决定使用其他方法,因此我没有得到全面测试解决方案的机会,由于方向发生变化,我的评分完整。