简体   繁体   中英

Linq to XML Query not picking anything

I have a rather complex XML document

<ItemSearchResponse xmlns="-------">
  <OperationRequest>
    <HTTPHeaders>
    </HTTPHeaders>
    <RequestId>0S57WGDPNC7T8HNBV76K</RequestId>
    <Arguments>
    </Arguments>
    <RequestProcessingTime>0.441776990890503</RequestProcessingTime>
  </OperationRequest>
  <Items>
    <Request>
      <ItemSearchRequest>
      </ItemSearchRequest>
    </Request>
    <TotalResults>1020</TotalResults>
    <TotalPages>102</TotalPages>
    <Item>
      <ASIN>B004WL0L9S</ASIN>
      <SalesRank>1</SalesRank>
      <ItemAttributes>
         <Manufacturer>Georgia Pacific Consumer Products LP (Cut-Sheet Paper)</Manufacturer>
         <Title>GP Copy &amp; Print Paper, 8.5 x 11 Inches Letter Size, 92 Bright White, 20    Lb, Ream of 500 Sheets (998067R)</Title>
      <ItemAttributes>
    </Item>
  <Items>

I run this query over it and it returns of list of zero:

XDocument doc = XDocument.Load(url);
List<Item> Items = (from c in doc.Elements("Item")
          select new Item
          {
            Title = c.Element("Title").Value
            SaleRank = c.Element("SaleRank").Value
            ASIN = c.Element("ASIN").Value
           }).ToList<Item>();

I am really new to XLinq but according to the documentation that should work.

First of all you have not valid xml. Here is example how it should looks:

<ItemSearchResponse >
    <OperationRequest>
        <HTTPHeaders> </HTTPHeaders>
        <RequestId>0S57WGDPNC7T8HNBV76K</RequestId>
        <Arguments> </Arguments>
        <RequestProcessingTime>0.441776990890503</RequestProcessingTime>
    </OperationRequest>
    <Items>
        <Request>
            <ItemSearchRequest> </ItemSearchRequest>
        </Request>
        <TotalResults>1020</TotalResults>
        <TotalPages>102</TotalPages>
        <Item>
            <ASIN>B004WL0L9S</ASIN>
            <SalesRank>1</SalesRank>
            <ItemAttributes>
                <Manufacturer>Georgia Pacific Consumer Products LP (Cut-Sheet Paper)</Manufacturer>
                <Title>GP Copy &amp; Print Paper, 8.5 x 11 Inches Letter Size, 92 Bright White, 20 Lb, Ream of 500 Sheets (998067R)</Title>
            </ItemAttributes>
        </Item>
    </Items>
</ItemSearchResponse>

And this code works with it:

var Items = (from c in doc.Root.Element("Items").Elements("Item")
                  select new Item()
                  {
                    Title = c.Element("ItemAttributes").Element("Title").Value,
                    SaleRank = c.Element("SalesRank").Value,
                    ASIN = c.Element("ASIN").Value
                   }).ToList();

or with Descendants :

var Items = (from c in doc.Root.Descendants("Item")
                  select new
                  {
                    Title = c.Element("ItemAttributes").Element("Title").Value,
                    SaleRank = c.Element("SalesRank").Value,
                    ASIN = c.Element("ASIN").Value
                   }).ToList();

The problem lies in your use of .Elements(XName) which it seems you're assuming is recursive. It is not, It only inspects direct children of the target (in this case the document).

I believe the function you're looking for is .Descendants(XName) which will look recursively, but be warned this is not very fast on massive XML docs.

The problem is the difference between Elements and Descendants

  var items = (from c in doc.Descendants("Item")
               select new Item
               {
                 Title = c.Element("ItemAttributes").Element("Title").Value,
                 SaleRank = c.Element("SalesRank").Value,
                 ASIN = c.Element("ASIN").Value
               }).ToList<Item>();

Elements a list of Xml Elements directly underneath the current Element (ie only 1 level deep). Descendants will retrieve all elements.

Based on your Xml and your query, I showed the use of Descendant and Element. The initial loop uses Descendants(), but access to Title uses to chained Element() calls.

I tried running the code, and I'm assuming the xmlns was removed for posting, but your actual code has a real namespace in it. If not, that maybe a problem you need to resolve first.

Turns out I need to add the namespace to query.

XNamespace ns = NAMESPACE;

var items = (from c in doc.Descendants(ns +"Item")
    select new Item
    {
       Title = c.Element(ns + "ItemAttributes").Element(ns + "Title").Value,
       SalesRank = c.Element(ns +"SalesRank").Value,
       ASIN = c.Element(ns + "ASIN").Value
    }).ToList<Item>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM