web-dev-qa-db-fra.com

ajout de sous-éléments XML

Avec PowerShell, je veux ajouter plusieurs sous-éléments dans une arborescence XML.
Je sais AJOUTER UN élément, je sais ajouter un ou plusieurs attributs, mais je ne comprends pas comment AJOUTER PLUSIEURS éléments.

Une façon serait de écrire une arborescence sous-XML sous forme de texte
Mais je ne peux pas utiliser cette méthode car les éléments ne sont pas ajoutés en même temps.

Pour ajouter un élément, je fais cela:

[xml]$xml = get-content $nomfichier
$newEl = $xml.CreateElement('my_element')
[void]$xml.root.AppendChild($newEl)

Fonctionne bien. Cela me donne cet arbre XML:

$xml | fc
class XmlDocument
{
  root =
    class XmlElement
    {
      datas =
        class XmlElement
        {
          array1 =
            [
              value1
              value2
              value3
            ]
        }
      my_element =     <-- the element I just added
    }
}

Maintenant, je veux ajouter un sous-élément à 'my_element'. J'utilise une méthode similaire:

$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)

Cela donne cet arbre XML (partiellement affiché):

my_element =
  class XmlElement
  {
    my_sub_element =
    another_one =
  }

Ce sont des attributs, pas des sous-éléments.
Les sous-éléments seraient affichés comme suit:

my_element =
  [
    my_sub_element
    another_one
  ]

Question : Comment ajouter plusieurs sous-éléments, un à la fois?

25
Gregory MOUSSAT

Jetez un œil à l'exemple suivant:

# 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")

Édité

Remarque: L'utilisation d'un chemin relatif dans Save ne fera pas ce que vous attendez .

41
JPBlanc

Je préfère créer du XML à la main, au lieu d'utiliser l'API pour le construire nœud par nœud, car à mon humble avis, il sera beaucoup plus lisible et plus maintenable.

Voici un exemple:

$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)
31
Erti-Chris Eelmaa

Vérifiez cet exemple de code. Il a tout ce dont vous avez besoin pour créer du XML à partir de zéro:

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()
}

... utilisons maintenant les deux fonctions pour créer et afficher un nouvel objet XML:

$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)

le résultat ressemble à ceci:

Formatted XML:

 <?xml version="1.0" encoding="utf-16"?>
<a>
  <b>
    <c>value</c>
    <d attrib="attrib_value" />
  </b>
</a>
2
Peter