XElement.Element failed to select the correct child node

时间:2016-02-03 03:08:16

标签: xml vb.net linq

I have the following XML:

<inventory>
  <item>
    <stocktype>
      <type>Basket</type>
      <id>1</id>
      <parentId>0</parentId>
    </stocktype>
    <cost>10.00</cost>
    <quantity>1</quantity>
    <name>Golden Wick Basket</name>
    <note>
      <code>remark</code>
      <content>Be extra careful about the golden paint....</content> 
    </note> 
    <note>
      <code>usage</code>
      <content>DeluxFruitBasket</content> 
    </note>  
  </item>
  <item>
    <stocktype>
      <type>Fruit</type>
      <id>2</id>
      <parentId>1</parentId>
    </stocktype>
    <cost>6.00</cost>
    <quantity>10</quantity>
    <name>Apple</name>
    <note>
      <code>remark</code>
      <content>Please pick red apples only</content> 
    </note>
    <note>
      <code>usage</code>
      <content>DeluxFruitBasket</content> 
    </note>
  </item>
  <item>
    <stocktype>
      <type>Fruit</type>
      <id>3</id>
      <parentId>1</parentId>
    </stocktype>
    <cost>4.00</cost>
    <quantity>10</quantity>
    <name>Orange</name>
    <note>
      <code>remark</code>
      <content></content> 
    </note>
    <note>
      <code>usage</code>
      <content>DeluxFruitBasket</content> 
    </note>
  </item>
  <item>
    <stocktype>
      <type>Fruit</type>
      <id>4</id>
      <parentId>1</parentId>
    </stocktype>
    <cost>12.00</cost>
    <quantity>1</quantity>
    <name>Pineapple</name>
  </item>
</inventory>

I have tried this LINQ to XML query but it always evaluated to false:

If(_rootElement.Descendants("item").Any(Function (x) x.Element("stocktype").Element("type").Value = "Fruit" And x.Element("note").Element("content").Value = "DeluxFruitBasket")) 

and I have used linqpad to check and replace Any() with Where() and the query returned null.

Question:

  • Why is the query returned null?
  • I also discovered that x.Element("note").Element("content") will always select the first "note" element from the two, why?
  • I can not change the structure of the XML as it is a standard in my company, how can I rewrite the query to archive my intent?

Thank you very much.

1 个答案:

答案 0 :(得分:0)

"Why is the query returned null?"

Because none of item element in your XML has first content equals "DeluxFruitBasket" (why it has to be the first content within item is related to question no 2)

"I also discovered that x.Element("note").Element("content") will always select the first "note" element from the two, why? "

Because you use Element() instead of plural Elements(). The latter will return all matched elements as you intended.

This is one possible LINQ to get all item containing "Fruit" stocktype and at least one "DeluxFruitBasket" content (replace Where with Any to use this in your code) :

Dim result = doc.Root.
                 Descendants("item").
                 Where(Function(x) x.Element("stocktype").
                                     Element("type").Value = "Fruit" _
                                     AndAlso _
                                   x.Elements("note").
                                     Elements("content").
                                     Any(Function(c) c.Value = "DeluxFruitBasket"))

dotnetfiddle demo