views:

727

answers:

2
Dim names() As String = {"one", "two", "three"}
Dim xml As XElement = Nothing
For Each name In names
  If xml Is Nothing Then
    xml = New XElement(name)
  Else
    xml.Add(New XElement(name)
  End If
Next

The above code will create something like this:

  <One>
    <Two />
    <Three />
  </One>

What I need is something like this:

  <One>
    <Two>
      <Three />
    </Two>
  </One>

I tried using xml.Elements.Last.Add(New XElement(name)), but the Last method isn't necessarily returning the last element for some reason.

Thanks!

A: 

Looks like you just want to add on an XElement -- don't use.Last or anything else, adding after the last one is the default behavior..

IOW:

You can say:

Dim node1 as XElement = new XElement( "A1")
Dim node2 as XElement = new XElement( "A2")
Dim node3 as XElement = new XElement ("A3")
node2.Add( node3)
Dim root as XElement = new XElement("Root",new XElement(){node1,node2})

To get:

<Root>
  <A1 />
  <A2>
    <A3 />
  </A2>
</Root>

Or do the same with:

Dim node1 as XElement = new XElement( "A1")
Dim node2 as XElement = new XElement( "A2")
Dim node3 as XElement = new XElement ("A3")
Dim root as XElement = new XElement("Root")
Dim children as XElement() = new XElement(){node1,node2}
for each child in children 
 root.add( child)
 if child.Name = "A2"
  child.Add( node3)
 end if
next

If you're looking for the last node to start in the tree (A3 in the example above), you want:

root.Descendants().Last()

Is this what you're really after (when asking questions liek this, it's good to give a tree and say which nodes you want to isolate)?

Ruben Bartelink
+1  A: 

A small change to your current code will do what you want:

Dim names() As String = {"one", "two", "three"}
Dim xml As XElement = Nothing
For Each name In names
  Dim new_elem As New XElement(name)
  If xml IsNot Nothing Then
      xml.Add(new_elem)
  End If
  xml = new_elem
Next

EDIT:

You can introduce another variable to store the root element:

Function BuildTree() As XElement
    Dim tree As XElement = Nothing

    Dim names() As String = {"one", "two", "three"}
    Dim xml As XElement = Nothing
    For Each name In names
        Dim new_elem As New XElement(name)
        If tree Is Nothing Then
            tree = new_elem
        Else
            xml.Add(new_elem)
        End If
        xml = new_elem
    Next

    Return tree
End Function
Bojan Resnik
I believe this is what I want. If this code were in a function, how would I return the entire tree that I built as the result if `xml` ends up referring to the last child element?
vg1890
Please see the updated answer: simply store the first created element in a variable that will not be modified by the function
Bojan Resnik