1

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.

Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
Joe Tyman
  • 1,417
  • 5
  • 28
  • 57

4 Answers4

1

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();
Samich
  • 29,157
  • 6
  • 68
  • 77
  • I trying to use it against the webresponse I am getting returned to me. Other than missing that closing tag, that is copy and pasted version of it. – Joe Tyman Oct 10 '11 at 16:20
0

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.

Aren
  • 54,668
  • 9
  • 68
  • 101
0

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 (i.e. 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.

Andre
  • 754
  • 1
  • 10
  • 16
0

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>();
Joe Tyman
  • 1,417
  • 5
  • 28
  • 57