2012-06-11 16 views
21

Przy pomocy PowerShell chcę dodać kilka podelementów do drzewa XML.
Znam ADD ONE element, wiem, aby dodać jeden lub kilka atrybutów, ale nie rozumiem, jak dodać kilka elementów.Dodawanie podelementów XML

Jednym ze sposobów może być write a sub-XML tree as text
Ale nie mogę użyć tej metody, ponieważ elementy nie są dodawane jednocześnie.

Aby dodać jeden element, to zrobić:

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

działa dobrze. To daje mi to drzewo XML:

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

Teraz chcę dodać element podrzędny do "my_element". Używam podobną metodę:

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

To daje to drzewo XML (ciowo wyświetlany):

my_element = 
    class XmlElement 
    { 
    my_sub_element = 
    another_one = 
    } 

Są to atrybuty, nie podelementów.
podelementów będzie wyświetlany jako to:

my_element = 
    [ 
    my_sub_element 
    another_one 
    ] 

Pytanie: Jak mogę dodać kilka mniejszych elementów, jeden na raz?

Odpowiedz

35

Wystarczy popatrzeć na poniższym przykładzie:

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

edytowany

uwaga: Using a relative path in Save will not do what you expect.

+1

O wiele lepsze rozwiązanie niż to, co do tej pory znalazłem! I czystsze. Dzięki. –

+0

To działa dobrze. Moim problemem jest to, że zapisuje wiele rzeczy na konsoli. Debugowanie pokazuje, że dzieje się to w tym wierszu: $ xmlSubElt.AppendChild ($ xmlSubText) , jeśli napiszę "> $ null" na końcu. Coś innego jest napisane Czy mogę to zablokować? – Tomi

+0

Zamień '> $ null' na' | out-null ". – JPBlanc

21

Wolę tworzyć xml ręcznie, zamiast używać API do budowania węzła po węźle, ponieważ ręcznie będzie znacznie bardziej czytelny i łatwiejszy w utrzymaniu.

Oto przykład:

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

Dzięki, właśnie tego szukałem! –

+0

To zadziałało bardzo dobrze dla mnie. I lubię być w stanie skonstruować i przeczytać xml w bardziej naturalny sposób, jak już zaznaczyłeś. – rrirower

+0

Zapisane jako funkcja (i prawdopodobnie lepiej obsługuje przestrzenie nazw?) Na stronie https://gist.github.com/thoemmi/2937183 –

1

Sprawdź ten kod-próbka. Ma wszystko, czego potrzebujesz, aby stworzyć XML z Cratch:

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

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