Microsoft Developer Network >
Forums Home
>
Archived Forums Forums
>
LINQ Project General
>
Linq to XML Help
Linq to XML Help
Hi I have the following xml file that I am wanting to use:
<?xml version="1.0" encoding="utf-8"?> <Roles> <Role name="Admin"> <user>user1</user> <user>user2</user> </Role> <Role name="User"> <user>user1</user> <user>user2</user> <user>user3</user> </Role> <Role name="Guest"> <user>user4</user> <user>user5</user> </Role> <Role name="Power User"> <user>user3</user> </Role> </Roles>I have the following class with this:
Public Class Role Public RoleName As String Public AssignedUsers As New StringCollection() End Class
I am using the following code to try and fill the object/class created with the data from the xml file:
Dim doc As XDocument = XDocument.Load(fileName) Dim query = From xElem In doc.Descendants("Role") Select New With { _ .RoleName = xElem.Attribute("name").Value, _ .AssignedUsers = xElem.Element("user").Value} _Roles = query_Roles is declared with the following:
Private _Roles As List(Of Role)
The query works to an extent that it selects all the roles and JUST one user but will not allow itself to be placed into the object. I have tried a Directcast the the object but that does not work either!
Can anyone see where I am going wrong in placing the query in the store I am using for the roles within my app I am trying but at this moement failing miserably to create!??
Thanks!
Tuppers
Answers
- For starters, you're creating an anonymous type. Note you haven't specified the type after "New" in your select statement. Change it to this:
Dim query = From xElem In doc.Descendants("Role") Select New Role With { _
.RoleName = xElem.Attribute("name").Value, _
.AssignedUsers = xElem.Element("user").Value}
Next, you need to check the type of the AssignedUsers property. It's currently StringCollection. Change it to a List(Of String). It should now look like this:
Public Class Role
Public RoleName As String
Public AssignedUsers As List(Of String)
End Class
Next, we're going to change what we're getting from the query again. This query modifies the one above, and is the final revision:
Dim query = From xElem In doc.Descendants("Role") Select New Role With { _
.RoleName = xElem.Attribute("name").Value, _
.AssignedUsers = xElem.Elements("user").Select(Function(x) x.Value).ToList()}
Now, LINQ queries return an IEnumerable(Of T), not a List(Of T), so you have two options here. Either change the type of _Roles to an IEnumerable(Of Role), or use the .ToList() method off of query to convert the IEnumerable(Of T) to a List(Of T):
_Roles = query.ToList();
Make those changes, and it should work fine.
Coding Light - Illuminated Ideas and Algorithms in Software
Coding Light Wiki • LinkedIn • ForumsBrowser- Marked As Answer byTuppers360 Wednesday, November 04, 2009 6:44 PM
- I wouldn't use a StringCollection in .NET 3.5 code. Why don't you use a List<string> e.g.
Public Class Role Private _roleName As String Public Property RoleName() As String Get Return _roleName End Get Set(ByVal value As String) _roleName = value End Set End Property Private _assignedUsers As List(Of String) Public Property AssignedUsers() As List(Of String) Get Return _assignedUsers End Get Set(ByVal value As List(Of String)) _assignedUsers = value End Set End Property End Class
Dim doc As XDocument = XDocument.Load(FileName) Dim query As IEnumerable(Of Role) = _ From role In doc.Root.Elements("Role") _ Select New Role With { _ .RoleName = CType(role.Attribute("name"), String), _ .AssignedUsers = role.Elements("user").Select(Function(u) CType(u, String)).ToList() _ } _Roles = query.ToList()
MVP XML My blog- Marked As Answer byTuppers360 Wednesday, November 04, 2009 6:44 PM
All Replies
- For starters, you're creating an anonymous type. Note you haven't specified the type after "New" in your select statement. Change it to this:
Dim query = From xElem In doc.Descendants("Role") Select New Role With { _
.RoleName = xElem.Attribute("name").Value, _
.AssignedUsers = xElem.Element("user").Value}
Next, you need to check the type of the AssignedUsers property. It's currently StringCollection. Change it to a List(Of String). It should now look like this:
Public Class Role
Public RoleName As String
Public AssignedUsers As List(Of String)
End Class
Next, we're going to change what we're getting from the query again. This query modifies the one above, and is the final revision:
Dim query = From xElem In doc.Descendants("Role") Select New Role With { _
.RoleName = xElem.Attribute("name").Value, _
.AssignedUsers = xElem.Elements("user").Select(Function(x) x.Value).ToList()}
Now, LINQ queries return an IEnumerable(Of T), not a List(Of T), so you have two options here. Either change the type of _Roles to an IEnumerable(Of Role), or use the .ToList() method off of query to convert the IEnumerable(Of T) to a List(Of T):
_Roles = query.ToList();
Make those changes, and it should work fine.
Coding Light - Illuminated Ideas and Algorithms in Software
Coding Light Wiki • LinkedIn • ForumsBrowser- Marked As Answer byTuppers360 Wednesday, November 04, 2009 6:44 PM
- I wouldn't use a StringCollection in .NET 3.5 code. Why don't you use a List<string> e.g.
Public Class Role Private _roleName As String Public Property RoleName() As String Get Return _roleName End Get Set(ByVal value As String) _roleName = value End Set End Property Private _assignedUsers As List(Of String) Public Property AssignedUsers() As List(Of String) Get Return _assignedUsers End Get Set(ByVal value As List(Of String)) _assignedUsers = value End Set End Property End Class
Dim doc As XDocument = XDocument.Load(FileName) Dim query As IEnumerable(Of Role) = _ From role In doc.Root.Elements("Role") _ Select New Role With { _ .RoleName = CType(role.Attribute("name"), String), _ .AssignedUsers = role.Elements("user").Select(Function(u) CType(u, String)).ToList() _ } _Roles = query.ToList()
MVP XML My blog- Marked As Answer byTuppers360 Wednesday, November 04, 2009 6:44 PM
- Super thanks for that!! I do have a few questions on what just happened! but i have no time at the mo to really digest I will repost more than likely tomorrow!
again thankyou! I am still learning! sorry!
Tuppers - Hi thanks for that yesterday I have a question about this part:
.AssignedUsers = role.Elements("user").Select(Function(u) CType(u, String)).ToList()
the select statement used here. I get that this selects the list of users within the role element. I have not seen this before could you please explain or point me in the direction of a good book for linq for this as well as in general and/or some online articles using this?
thanks again! - See the VB documentation on lamba expressions . With LINQ you have, for some queries, the choice between the query syntax and the method syntax. So
role.Elements("user").Select(Function(u) CType(u, String))
is the same as
From user In role.Elements("user") Select CType(u, String)
MVP XML My blog - Thanks your help is much appreciatted.
I am now having a problem with the following code as I have changed from the stringcollection to the List(Of String):
i think I should return an arry of results but I am not sure about changing the logic to get there.Public Overrides Function GetAllRoles() As String() Try Dim Results As String() = New String(CurrentStore.Roles.Count) {} For i As Integer = 0 To i < Results.Length Results(i) = CurrentStore.Roles(i).RoleName Next Return Results Catch ex As Exception Throw End Try End Function
Could you possibly help please?
regards
Tuppers and again thanks! Sorry if i should of created a new post! - I have tried something like:
Public Overrides Function GetAllRoles() As String() Try Dim Results As New List(Of String) Dim Role As List(Of Role) = CurrentStore.Roles If Role IsNot Nothing Then For Each r In Role NOT SURE WHAT TO PUT HERE!!! Next Else Throw New ProviderException("There are no roles to diplay!") End If Return Results.ToArray() Catch ex As Exception Throw End Try End FunctionAs you can see I am not sure what to place in the for loop!
- What is CurrentStore.Roles exactly? A List(Of Role)? If you want an array of role names then you can simply do
Return CurrentStore.Roles.Select(Function(r) r.RoleName).ToArray()
or if you prefer query syntax then e.g.
Return (From role In CurrentStore.Roles Select role.RoleName).ToArray()
MVP XML My blog - what can I say! thank you and thank you some more I should be able to move on quite a bit from here I think!! I do have some questions about handling multiple updates on an xml file but I will post that in he XML forum!
and thank you!
do you recommend any books for vb or linq? its nice sometimes to get away from the computer screen!
Cheers
Tuppers

