tags:

views:

781

answers:

2

I'm trying to learn LINQ and have a question on querying XML using VB.

My XML:

 <Procedure-Text>
    <A ID="marker1"></A>Do This Procedure
 </Procedure-Text>
 <Procedure-Text>
    <A ID="marker2"></A>Do That Procedure
 </Procedure-Text>

How can I specify my query to get only the procedure text that has the ID attribute marker2? In other words, I would like a resulting string that says Do That Procedure.

Thanks

A: 

The linq query is

from x 
in d.Descendants("A") 
where x.Attribute("ID").Value == "marker2" 
select x.NextNode

In other words, look for an element named A where it's ID attribute is "marker2" and take the immediate next node.

You'll probably want to do a FirstOrDefault() on the resulting enumeration to get out the XNode (its actually an XText) that has your text in it.

Will
+2  A: 

Use VB XML literals:

Dim marker2 = From x In data...<Procedure-Text> _
              Where x.<A>.@ID = "marker2" _
              Select x

The triple dot syntax produce "all descendants" of an xml element, i.e. data...<Procedure-Test> will produce a list of <Procedure-Test> tags inside data

The dot syntax on XML literals means "first descendant" so x.<A> will produce the first occurence of <A> inside x. Of which x is now instance of <Procedure-Test>

And now that you have the desired <A> element, comparing its id to a string is trivial with the @attr attribute selector. <A>.@ID = "marker2" will evaluate to True if the ID attribute of the <A> tag is equal to "marker2"

So x.<A>.@ID means "The ID attribute of the first <A> tag inside x"

And you want the <Procedure-Text> element, so you specify Select x

Full example:

Sub Main()

    Dim data = <doc>
                   <Procedure-Text>
                       <A ID="marker1"></A>Do This Procedure
                   </Procedure-Text>
                   <Procedure-Text>
                       <A ID="marker2"></A>Do That Procedure
                   </Procedure-Text>
               </doc>

    Dim marker2 = From x In data...<Procedure-Text> _
                  Where x.<A>.@ID = "marker2" _
                  Select x

    ' prints the second procedure-text element
    Console.WriteLine(marker2.FirstOrDefault().ToString())

    Console.ReadKey()

End Sub
chakrit
Works! Thanks!Instead of FirstOrDefault, I use Value to get the string I need.
mraviator
VB does have lots of support for xml that C# (my language of choice) is lacking. Its the only thing about VB I wish was in C#. I also didn't know that this support extends into duct-typing on XElements. Its pretty remarkable compiler magic.
Will