# Chain nesting XML elements

I have a scenario where I need to chain nest XmlElements, and I got a working solution using a recursive function, but I can't help but feel that it can be made better.

Here's my code so far:

function AppendChild
{
param
(
[string[]]$string,$obj,
[System.Xml.XmlDocument]$XML ) if ($string.Length -gt 0)
{
$child =$XML.CreateElement($string[0])$child.InnerText = ""
AppendChild -string ($string | Select -Skip 1) -obj$child -XML $XML$obj.AppendChild($child) } }$string = "this is a somewhat long string" -split " "

$XML = New-Object System.Xml.XmlDocument$root = $XML.CreateElement($string[0])

AppendChild -string ($string | Select -Skip 1) -obj$root -XML $XML$root.OuterXml # <this><is><a><somewhat><long><string></string></long></somewhat></a></is></this>


Any suggestions?

• Your code doesn't work for me. – Dangph Apr 28 '16 at 10:21
• @Dangph What error are you encountering? I've made some edits to the script to make it more compatible with other versions of PowerShell. – Negorath Apr 28 '16 at 12:46
• Sorry, I should have said why it didn't work. It was the [System.Xml.XmlDocument]::new(). Is that a new feature in PowerShell? – Dangph Apr 29 '16 at 0:08
• @Dangph Yes, I can't find any changelogs for it at the moment, but I belive it came with PowerShell 4. – Negorath Apr 29 '16 at 5:02
• I see. I have PS3. – Dangph Apr 29 '16 at 5:27

I don't think you need recursion. Just a simple loop will do. We can just keep a reference to the last element in the document, which we update every time we append a new element, and we keep appending to that.

$tagNames = "this is a somewhat long string" -split "\s+"$XML = New-Object System.Xml.XmlDocument

$lastElt =$XML

$tagNames | % {$elt = $XML.CreateElement($_)
$lastElt =$lastElt.AppendChild($elt) }$xml.OuterXml # <this><is><a><somewhat><long><string /></long></somewhat></a></is></this>


I also changed it to split the string on \s+, which is a regular expression meaning "one or whitespace characters", so that multiple consecutive spaces (or tabs or whatever) will be counted as a single thing as far as -split is concerned.

I change $string to $tagNames because it is important to name variables accurately otherwise you will confuse yourself.

• Excellent! It seems so obvious now, it's even much faster according to my tests. Thanks for your answer :) – Negorath Apr 29 '16 at 4:55