With PowerShell, I want to add several sub-elements into an XML tree.
I know to ADD ONE element, I know to add one or several attributes, but I don't understand how to ADD SEVERAL elements.
One way whould be to write a sub-XML tree as text
But I can't use this method because the elements are not added at once.
To add one element, I do that:
[xml]$xml = get-content $nomfichier
$newEl = $xml.CreateElement('my_element')
[void]$xml.root.AppendChild($newEl)
Works fine. This give me this XML tree:
$xml | fc
class XmlDocument
{
root =
class XmlElement
{
datas =
class XmlElement
{
array1 =
[
value1
value2
value3
]
}
my_element = <-- the element I just added
}
}
Now I want to add a sub element to 'my_element'. I use a similar method:
$anotherEl = $xml.CreateElement('my_sub_element')
[void]$xml.root.my_element.AppendChild($anotherEl) <-- error because $xml.root.my_element is a string
[void]$newEl.AppendChild($anotherEl) <-- ok
$again = $xml.CreateElement('another_one')
[void]$newEl.AppendChild($again)
This give this XML tree (partialy displayed):
my_element =
class XmlElement
{
my_sub_element =
another_one =
}
Those are attributes, not sub-elements.
Sub-elements would be displayed as this:
my_element =
[
my_sub_element
another_one
]
Question: How do I add several sub-elements, one at a time?
XML documents are formed as element trees. An XML tree starts at a root element and branches from the root to child elements. All elements can have sub elements (child elements): <root>
An element can have multiple unique attributes. Attribute gives more information about XML elements. To be more precise, they define properties of elements. An XML attribute is always a name-value pair.
Have a look to the following example :
# Document creation
[xml]$xmlDoc = New-Object system.Xml.XmlDocument
$xmlDoc.LoadXml("<?xml version=`"1.0`" encoding=`"utf-8`"?><Racine></Racine>")
# Creation of a node and its text
$xmlElt = $xmlDoc.CreateElement("Machine")
$xmlText = $xmlDoc.CreateTextNode("Mach1")
$xmlElt.AppendChild($xmlText)
# Creation of a sub node
$xmlSubElt = $xmlDoc.CreateElement("Adapters")
$xmlSubText = $xmlDoc.CreateTextNode("Network")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
# Creation of an attribute in the principal node
$xmlAtt = $xmlDoc.CreateAttribute("IP")
$xmlAtt.Value = "128.200.1.1"
$xmlElt.Attributes.Append($xmlAtt)
# Add the node to the document
$xmlDoc.LastChild.AppendChild($xmlElt);
# Store to a file
$xmlDoc.Save("c:\Temp\Temp\Fic.xml")
Edited
Remark : Using a relative path in Save will not do what you expect.
I prefer creating xml by hand, instead of using API to construct it node by node, as imho by hand it will be much more readable and more maintable.
Here is an example:
$pathToConfig = $env:windir + "\Microsoft.NET\Framework64\v4.0.30319\Config\web.config"
$xml = [xml] (type $pathToConfig)
[xml]$appSettingsXml = @"
<appSettings>
<add key="WebMachineIdentifier" value="$webIdentifier" />
</appSettings>
"@
$xml.configuration.AppendChild($xml.ImportNode($appSettingsXml.appSettings, $true))
$xml.Save($pathToConfig)
Check this code-sample. It has everything you need to create XML from scratch:
function addElement($e1, $name2, $value2, $attr2)
{
if ($e1.gettype().name -eq "XmlDocument") {$e2 = $e1.CreateElement($name2)}
else {$e2 = $e1.ownerDocument.CreateElement($name2)}
if ($attr2) {$e2.setAttribute($value2,$attr2)}
elseif ($value2) {$e2.InnerText = "$value2"}
return $e1.AppendChild($e2)
}
function formatXML([xml]$xml)
{
$sb = New-Object System.Text.StringBuilder
$sw = New-Object System.IO.StringWriter($sb)
$wr = New-Object System.Xml.XmlTextWriter($sw)
$wr.Formatting = [System.Xml.Formatting]::Indented
$xml.Save($wr)
return $sb.ToString()
}
...now let's use both functions to create and display a new XML-object:
$xml = New-Object system.Xml.XmlDocument
$xml1 = addElement $xml "a"
$xml2 = addElement $xml1 "b"
$xml3 = addElement $xml2 "c" "value"
$xml3 = addElement $xml2 "d" "attrib" "attrib_value"
write-host `nFormatted XML:`r`n`n(formatXML $xml.OuterXml)
the result looks like this:
Formatted XML:
<?xml version="1.0" encoding="utf-16"?>
<a>
<b>
<c>value</c>
<d attrib="attrib_value" />
</b>
</a>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With