First, myXMLFile.Descendants("staff").Descendants("staffName") is redundant. Descendants return all elements at any level within an XDocument or XElement . So myXMLFile.Descendants("staffName") will give the same result.
Secondly, you can simply use the Element property and the Value property as follows:
staffBio = staff.Element("staffBio").Value
staff will have only one staffBio element, so there is no need to use the Descendants property. Value is a string, so you do not need to call Value.ToString . If the element is empty, then Value will return an empty string, and this is what you are looking for!
Thirdly, there is a much better (and I believe a more direct) way to do this in VB.NET. Here is a console application that demonstrates how to do this:
Module Module1 Sub Main() Dim myXMLFile = <allStaff> <staff> <staffName>Test Staff</staffName> <staffTitle>Slave</staffTitle> <staffDepartmentName>Finance</staffDepartmentName> <staffOffice>London</staffOffice> <staffEmail> t.staff@battens.co.uk </staffEmail> <staffPhone>0207 123 456</staffPhone> <staffNotes>Working hours Mon to Thurs 9.15 - 5.15</staffNotes> <staffBio></staffBio> </staff> <staff> <staffName>Other Staff</staffName> <staffTitle>Master</staffTitle> <staffDepartmentName>IT</staffDepartmentName> <staffOffice>Oxford</staffOffice> <staffEmail> o.staff@battens.co.uk </staffEmail> <staffPhone>0207 123 789</staffPhone> <staffNotes></staffNotes> <staffBio>Some guy.</staffBio> </staff> </allStaff> Dim search = "Test" Dim searchQuery = From staff In myXMLFile...<staff> _ Where staff.<staffName>.Value.Contains(search) _ Select si = New StaffInfo With {.Name = staff.<staffName>.Value, _ .Title = staff.<staffTitle>.Value, _ .Department = staff.<staffDepartmentName>.Value, _ .Office = staff.<staffOffice>.Value, _ .Email = staff.<staffEmail>.Value, _ .Phone = staff.<staffPhone>.Value, _ .Notes = staff.<staffNotes>.Value, _ .Bio = staff.<staffBio>.Value} For Each staff In searchQuery Console.WriteLine("Name: {0}", staff.Name) Console.WriteLine("Title: {0}", staff.Title) Console.WriteLine("Department: {0}", staff.Department) Console.WriteLine("Office: {0}", staff.Office) Console.WriteLine("Email: {0}", staff.Email) Console.WriteLine("Phone: {0}", staff.Phone) Console.WriteLine("Notes: {0}", staff.Notes) Console.WriteLine("Bio: {0}", staff.Bio) Console.WriteLine() Next Console.ReadLine() End Sub Private Class StaffInfo Private _name As String Public Property Name() As String Get Return _name End Get Set(ByVal value As String) _name = value End Set End Property Private _title As String Public Property Title() As String Get Return _title End Get Set(ByVal value As String) _title = value End Set End Property Private _department As String Public Property Department() As String Get Return _department End Get Set(ByVal value As String) _department = value End Set End Property Private _office As String Public Property Office() As String Get Return _office End Get Set(ByVal value As String) _office = value End Set End Property Private _email As String Public Property Email() As String Get Return _email End Get Set(ByVal value As String) _email = value End Set End Property Private _phone As String Public Property Phone() As String Get Return _phone End Get Set(ByVal value As String) _phone = value End Set End Property Private _notes As String Public Property Notes() As String Get Return _notes End Get Set(ByVal value As String) _notes = value End Set End Property Private _bio As String Public Property Bio() As String Get Return _bio End Get Set(ByVal value As String) _bio = value End Set End Property End Class End Module
If you have an XML file (.xsd), you can import the link to this xmlns into the VB source file, which will give you intellisense to write your LINQ to XML queries.
( Edit: A quick way to create a schema is to open the XML file in Visual Studio and select "Create Schema" in the XML menu.)
For more information and help, please watch the βLike Meβ video on LINQ by Beth Massi .