views:

3085

answers:

2

I am querying an HTML file with LINQ-to-XML. It looks something like this:

<html>
    <body>
        <div class="Players">
        <div class="role">Goalies</div>
        <div class="name">John Smith</div>
        <div class="name">Shawn Xie</div>
        <div class="role">Right Wings</div>
        <div class="name">Jack Davis</div>
        <div class="name">Carl Yuns</div>
        <div class="name">Wayne Gortonia</div>
        <div class="role">Centers</div>
        <div class="name">Lutz Gaspy</div>
        <div class="name">John Jacobs</div>
        </div>
    </body>
</html>

What I'm trying to do is create a list of these folks like in a list of a structure called Players:

Structure Players
    Public Name As String
    Public Position As String
End Structure

But I've quickly found out I don't really know what I'm doing when it comes to LINQ.

I've got this far in my queries:

Dim goalieList = From d In player.Elements _
                 Where d.Value = "Goalies" _
                 Select From g In d.ElementsAfterSelf _
                 Take While (g.@class <> "role") _
                 Select New Players With {.Position = "Goalie", _
                         .Name = g.Value}

Dim centersList = From d In player.Elements _
                  Where d.Value = "Centers" _
                  Select From g In d.ElementsAfterSelf _
                  Take While (g.@class <> "role") _
                  Select New Players With {.Position = "Centers", _
                         .Name = g.Value}

Which gets me down to the players by position, but then I can't do much with this afterwards the result type is System.Collections.Generic.IEnumerable(Of System.Collections.Generic.IEnumerable(Of Player))

What I want to do is add these two results to a new list, like:

Dim playersList As List(Of Players) = Nothing
playersList.AddRange(centersList)
playersList.AddRange(goalieList)

So that I can then query the list and use it. But it kicks the error:

Unable to cast object of type 'WhereSelectEnumerableIterator2[System.Xml.Linq.XElement,System.Collections.Generic.IEnumerable1[Players]]' to type 'System.Collections.Generic.IEnumerable`1[Players]'

As you can see, I may really have no idea how to work with all these objects/classes. Does anyone have any insight on what I may be doing wrong and how I can resolve it?

RESOLVED: The LINQ query needs to return a single IEnumerable, like this:

Dim goalieList = From l In _
                    (From d In players.Elements _
                     Where d.Value = "Goalies" _
                     Select d.ElementsAfterSelf.TakeWhile(Function(f) f.@class <> "role")) _
                  Select New Players With {.Position = "Goalie", .Name = l.Value}

and then use goalieList.ToList

+3  A: 

I fail at VB, but in C# you would call ToList() on the centersList and goalieList.

So something like:

playersList.AddRange(centersList.ToList())
playersList.AddRange(goalieList.ToList())
Alan
You gave me a good hint here. I figured it out, I believe. The issue was that I had two select statements which was creating an iEnumerable within an iEnumerable. I changed my code to:Dim goalieList = From l In (From d In players.Elements Where d.Value = "Goalies" Select d.ElementsAfterSelf.TakeWhile(Function(f) f.@class <> "role")) Select New Players With {.Position = "Goalie", .Name = l.Value}which then returns a single iEnumerable. Witht this, I do as you suggested - playersList.AddRange(goalieList.ToList()) - and it works!
Otaku
+1  A: 

Any chance that you have two Players classes? Otherwise, I don't see how you could possibly get that error message.

Looking into Reflector, WhereSelectEnumerableIterator implements IEnumerable, so the cast should succeed.

Igor ostrovsky