VB.NET Query Linq for get all elements node

I'm try to understandin Linq to XML and I've this file XML:

<?xml version="1.0" encoding="utf-8"?>
<Headers  xmlns="http://tempuri.org/GridLayerSchema.xsd">
  <Header>
   <Name>Layer0</Name>
    <Fields FieldID="FieldID0" FieldName="FieldNameAll" FieldPosition="0" FieldPositionStart="0" FieldLenght="254" FieldEnable="true" />
   </Header>
  <Header>
   <Name>Layer1</Name>
   <Fields FieldID="FieldID0" FieldName="JetPosition" FieldPosition="0" FieldPositionStart="0" FieldLenght="14" FieldEnable="true" />
   <Fields FieldID="FieldID1" FieldName="Owner" FieldPosition="1" FieldPositionStart="14" FieldLenght="14" FieldEnable="true" />
   <Fields FieldID="FieldID2" FieldName="Item" FieldPosition="2" FieldPositionStart="28" FieldLenght="3" FieldEnable="true" />
  </Header>
</Headers>

I'll try to take all elements with a linq query for making a VB.net class, somethink like this:

 Class Field:
  Public Class Field
  Public Property FieldID1 As String
  Public Property FieldName As String
  Public Property FieldPosition As Integer
  Public Property FieldPositionStart As Integer
  Public Property FieldLenght As Integer
  Public Property FieldEnable As Boolean
End Class

Then the Header class:

Public Class Header : Inherits Field
  Public Property Name As String
End Class

In this one I'va a function for making a Headers collection:

Public Shared Function HeadersLoader() As Headers
    Dim HeadersCollection As New Headers
    Dim ns As XNamespace = "http://tempuri.org/GridLayerSchema.xsd"
    Dim xdoc As XDocument = XDocument.Load(My.Application.Info.DirectoryPath & "\Layers\Headers.xml")

     Dim HeadersQuery = From Header In xdoc.Root.Elements(ns + "Header")
                       Select Header
    For Each e In HeadersQuery
        Dim _mHeader As New Header
        With _mHeader
            .Name = e.Value.ToString
        End With
        HeadersCollection.Add(_mHeader)
    Next
    Return HeadersCollection
   End Function

Now I've two questions:

  • Why I've the Header's name in Value property and not in Name property (in name property I've all the namespace and the header tag, but not the name: {http://tempuri.org/GridLayerSchema.xsd}Header )

  • How can I read all fields of the current Header?I need a nested query? I'll thought, with my query, to find all but seems not so, I can read only the first node.

Jon Skeet
people
quotationmark

You're being confused by the fact that the Value property on XElement will concatenate all the text nodes within an element, including within descendants. That happens to be getting the text value of the Name child element, because that's the only element you've got with any text. It would be better to write:

With _mHeader
    .Name = e.Element(ns + "Name").Value

That way you're explicitly asking for the text within the <Name> child element.

Now your class design is a bit messed up because you're saying that a header is a field, rather than that it has a list of fields. I think you should have something like:

Public Class Header
  Public Property Name As String
  Public Property Fields As List(Of Field)
End Class

(possibly with some initialization). I would then change your LINQ query to create the instances of Header within the Select clause. I'm not going to attempt the VB, but in C# I'd have something like:

var headers = xdoc.Root.Elements(ns + "Header")
                  .Select(header => new Header
                  {
                      Name = header.Element("Name").Value,
                      Fields = header.Elements("Fields")
                                     .Select(field => new Field
                                     {
                                         FieldID1 = field.Element("FieldID)".Value,
                                         // etc
                                     })
                                     .ToList();
                  });

You might want to add static FromXElement methods to Header and Field (where Header.FromXElement would use Field.FromXElement) to make this all a bit simpler.

people

See more on this question at Stackoverflow