Need Help with Linq to Xml

  • Thread starter Thread starter Roshawn
  • Start date Start date
R

Roshawn

Hi,

My usage of Linq to Xml has been going great until now. I'm getting an error whenever I
don't find a particular node in the xml, even though I use an auxiliary function to test
for it. Here's what my code looks like (note that I'm using Amazon Web Services):

Imports <xmlns="http://webservices.amazon.com/AWSECommerceService/2007-06-13">
....
....
....

Private Sub GetAmazonStuff()
'code to actually call Amazon Web Services omitted
Dim MyNodes = (From nd In doc...<Item> _
Select New Item With {.ASIN = nd.<ASIN>.Value, _
.Image = nd.<SmallImage>.<URL>.Value, _
.Title = nd.<ItemAttributes>.<Title>.Value, _
.ListPrice = TestNode(nd.<ItemAttributes>.<ListPrice>), _
.OurPrice = TestNode(nd.<Offers>.<Offer>.<OfferListing>.<Price>)})
bindingSource.DataSource = MyNodes.ToList() 'error always occurs here & points to MyNodes
Me.dgvAmazon.DataSource = bindingSource
End Sub

Private Function TestNode(ByVal element As XElement) As String
If Not (element) Is Nothing Then
Return element.<FormattedPrice>.Value
Else
Return "no data"
End If
End Function


When running this code, I always get the "Object not set to an instance of an object"
error directed at the MyNodes variable. Code execution stops (as indicated above) despite
there being other nodes that haven't been evaluated. Debugging revealed that the error is
thrown whenever the TestNode function finds that the element Is Nothing, which means it
doesn't exist.

Why does that happen?

Thanks,
Roshawn
 
Roshawn said:
Dim MyNodes = (From nd In doc...<Item> _
Select New Item With {.ASIN = nd.<ASIN>.Value, _
.Image = nd.<SmallImage>.<URL>.Value, _
.Title = nd.<ItemAttributes>.<Title>.Value, _
.ListPrice = TestNode(nd.<ItemAttributes>.<ListPrice>),
nd.<ItemAttributes>.<ListPrice>
returns IEnumerable(Of XElement) and not XElement which your function
TestNode expects.

_
.OurPrice = TestNode(nd.<Offers>.<Offer>.<OfferListing>.<Price>)})

Same here.
Private Function TestNode(ByVal element As XElement) As String
If Not (element) Is Nothing Then
Return element.<FormattedPrice>.Value
Else
Return "no data"

It is not clear to me what you want to achieve. Please post a relevant
sample of the XML your are trying to extract data from, then describe
which data you want to extract, then we can help with the LINQ.
 
@Martin,

Thanks for the reply. Here is a sample of the xml I'm working with:

<ItemSearchResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2005-10-05">
<OperationRequest>
<HTTPHeaders>
<Header Name="UserAgent" Value="IE">
</Header>
</HTTPHeaders>
</OperationRequest>
<Items>
<Item>
<ASIN>B000VFN934</ASIN>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/419iznuXv1L._SL75_.jpg</URL>
<Height Units="pixels">75</Height>
<Width Units="pixels">75</Width>
</SmallImage>
<ItemAttributes>
<ListPrice>
<Amount>21800</Amount>
<CurrencyCode>USD</CurrencyCode>
<FormattedPrice>$218.00</FormattedPrice>
</ListPrice>
<Title>Arturo Italian Leather Triple Compartment Tote</Title>
</ItemAttributes>
</Item>
<Item>
<ASIN>B001534CZA</ASIN>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51Nw9o2xGGL._SL75_.jpg</URL>
<Height Units="pixels">41</Height>
<Width Units="pixels">75</Width>
</SmallImage>
<ItemAttributes>
<ListPrice>
<Amount>3600</Amount>
<CurrencyCode>USD</CurrencyCode>
<FormattedPrice>$36.00</FormattedPrice>
</ListPrice>
<Title>La Regale Satin Beaded Shoulder Clutch</Title>
</ItemAttributes>
</Item>
<Item>
<ASIN>B000VFS7UY</ASIN>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/41B2pi7FRgL._SL75_.jpg</URL>
<Height Units="pixels">75</Height>
<Width Units="pixels">75</Width>
</SmallImage>
<ItemAttributes>
<ListPrice>
<Amount>3200</Amount>
<CurrencyCode>USD</CurrencyCode>
<FormattedPrice>$32.00</FormattedPrice>
</ListPrice>
<Title>La Regale Beaded Satin Flap Clutch</Title>
</ItemAttributes>
</Item>
<Item>
<ASIN>B000090LU3</ASIN>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/31BN7EGXaLL._SL75_.jpg</URL>
<Height Units="pixels">75</Height>
<Width Units="pixels">75</Width>
</SmallImage>
<ItemAttributes>
<Title>Fontanelli Heart Shape Italian Polished Leather Handbag</Title>
</ItemAttributes>
<OfferSummary>
<LowestNewPrice>
<Amount>21300</Amount>
<CurrencyCode>USD</CurrencyCode>
<FormattedPrice>$213.00</FormattedPrice>
</LowestNewPrice>
<TotalNew>1</TotalNew>
<TotalUsed>0</TotalUsed>
<TotalCollectible>0</TotalCollectible>
<TotalRefurbished>0</TotalRefurbished>
</OfferSummary>
<Offers>
<Offer>
<OfferListing>
<Price>
<Amount>21300</Amount>
<CurrencyCode>USD</CurrencyCode>
<FormattedPrice>$213.00</FormattedPrice>
</Price>
</OfferListing>
</Offer>
</Offers>
</Item>
</Items>
</ItemSearchResponse>


As for nd.<ItemAttributes>.<ListPrice> returning IEnumerable (Of XElement) instead of
XElement, Intellisense shows that it does return XElement. If it were wrong, then my
TestNode function would throw a conversion error or something, no. I get zero errors at
compile time. It occurs only when I'm working with the xml.

Thanks,
Roshawn
 
Roshawn said:
@Martin,

Thanks for the reply. Here is a sample of the xml I'm working with:

<ItemSearchResponse
xmlns="http://webservices.amazon.com/AWSECommerceService/2005-10-05">
<OperationRequest>
<HTTPHeaders>
<Header Name="UserAgent" Value="IE">
</Header>
</HTTPHeaders>
</OperationRequest>
<Items>
<Item>
<ASIN>B000VFN934</ASIN>
<SmallImage>

<URL>http://ecx.images-amazon.com/images/I/419iznuXv1L._SL75_.jpg</URL>
<Height Units="pixels">75</Height>
<Width Units="pixels">75</Width>
</SmallImage>
<ItemAttributes>
<ListPrice>
<Amount>21800</Amount>
<CurrencyCode>USD</CurrencyCode>
<FormattedPrice>$218.00</FormattedPrice>
</ListPrice>
<Title>Arturo Italian Leather Triple Compartment Tote</Title>
</ItemAttributes>
</Item>
<Item>
<ASIN>B001534CZA</ASIN>
<SmallImage>

<URL>http://ecx.images-amazon.com/images/I/51Nw9o2xGGL._SL75_.jpg</URL>
<Height Units="pixels">41</Height>
<Width Units="pixels">75</Width>
</SmallImage>
<ItemAttributes>
<ListPrice>
<Amount>3600</Amount>
<CurrencyCode>USD</CurrencyCode>
<FormattedPrice>$36.00</FormattedPrice>
</ListPrice>
<Title>La Regale Satin Beaded Shoulder Clutch</Title>
</ItemAttributes>
</Item>
<Item>
<ASIN>B000VFS7UY</ASIN>
<SmallImage>

<URL>http://ecx.images-amazon.com/images/I/41B2pi7FRgL._SL75_.jpg</URL>
<Height Units="pixels">75</Height>
<Width Units="pixels">75</Width>
</SmallImage>
<ItemAttributes>
<ListPrice>
<Amount>3200</Amount>
<CurrencyCode>USD</CurrencyCode>
<FormattedPrice>$32.00</FormattedPrice>
</ListPrice>
<Title>La Regale Beaded Satin Flap Clutch</Title>
</ItemAttributes>
</Item>
<Item>
<ASIN>B000090LU3</ASIN>
<SmallImage>

<URL>http://ecx.images-amazon.com/images/I/31BN7EGXaLL._SL75_.jpg</URL>
<Height Units="pixels">75</Height>
<Width Units="pixels">75</Width>
</SmallImage>
<ItemAttributes>
<Title>Fontanelli Heart Shape Italian Polished Leather
Handbag</Title>
</ItemAttributes>
<OfferSummary>
<LowestNewPrice>
<Amount>21300</Amount>
<CurrencyCode>USD</CurrencyCode>
<FormattedPrice>$213.00</FormattedPrice>
</LowestNewPrice>
<TotalNew>1</TotalNew>
<TotalUsed>0</TotalUsed>
<TotalCollectible>0</TotalCollectible>
<TotalRefurbished>0</TotalRefurbished>
</OfferSummary>
<Offers>
<Offer>
<OfferListing>
<Price>
<Amount>21300</Amount>
<CurrencyCode>USD</CurrencyCode>
<FormattedPrice>$213.00</FormattedPrice>
</Price>
</OfferListing>
</Offer>
</Offers>
</Item>
</Items>
</ItemSearchResponse>


Here is a query that works with your sample:

Dim responseDoc As XDocument = XDocument.Load("..\..\XMLFile1.xml")
Dim query = _
From nd In responseDoc...<Item> _
Let listPrice = nd.<ItemAttributes>.<ListPrice>(0) _
Let offers = nd.<Offers>(0) _
Select New With { _
.ASIN = nd.<ASIN>.Value, _
.Image = nd.<SmallImage>.<URL>.Value, _
.Title = nd.<ItemAttributes>.<Title>.Value, _
.ListPrice = TestPrice(listPrice), _
.OurPrice = TestOffers(offers)}

For Each item In query
Console.WriteLine("ASIN: {0}, Image: {1}, Title: {2},
ListPrice: {3}, OurPrice: {4}", item.ASIN, item.Image, item.Title,
item.ListPrice, item.OurPrice)
Next


The functions TestPrice and TestOffers look as follows:

Private Function TestPrice(ByVal element As XElement) As String
If element IsNot Nothing Then
Return element.<FormattedPrice>.Value
Else
Return "no data"
End If
End Function

Private Function TestOffers(ByVal element As XElement) As String
If element IsNot Nothing Then
Return
element.<Offer>.<OfferListing>.<Price>.<FormattedPrice>.Value
Else
Return "no data"
End If
End Function
End Module
 
@Martin,

I appreciate the code you provided in your previous response. Didn't know much about the
"Let" parameter in Linq.

I ran this code and I received zero errors. Things work as expected. :)

Many thanks,
Roshawn
 
Back
Top