2012-06-11 4 views
21

С помощью PowerShell я хочу добавить несколько подэлементов в дерево XML.
Я знаю, чтобы добавить элемент ADD ONE, я знаю, чтобы добавить один или несколько атрибутов, но я не понимаю, как добавить несколько элементов.Добавление подэлементов XML

Один из способов: write a sub-XML tree as text
Но я не могу использовать этот метод, потому что элементы не добавляются сразу.

Чтобы добавить один элемент, я делаю это:

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

работает отлично. Это даст мне это дерево XML:

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

Теперь я хочу добавить подэлемент в 'my_element'. Я использую подобный метод:

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

Это дает этот XML-дерево (частично показан):

my_element = 
    class XmlElement 
    { 
    my_sub_element = 
    another_one = 
    } 

те атрибуты, не подэлементы.
Суб-элементы будут отображаться как это:

my_element = 
    [ 
    my_sub_element 
    another_one 
    ] 

Вопрос: Как добавить несколько суб-элементов, по одному за раз?

ответ

35

Посмотрите на следующий пример:

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

Отредактировано

Примечание: Using a relative path in Save will not do what you expect.

+1

Способ намного лучшего решения, чем то, что я нашел до сих пор! И чище. Благодарю. –

+0

Это работает хорошо. Моя проблема заключается в том, что он много пишет на консоли. Отладка показывает, что это происходит в этой строке: $ xmlSubElt.AppendChild ($ xmlSubText) , если я пишу «> $ null» до конца. Что-то еще выписано Могу ли я заблокировать его? – Tomi

+0

Замените '> $ null' на' | из-null'. – JPBlanc

21

Я предпочитаю создавать xml вручную, вместо того, чтобы использовать API для его сборки по узлам, так как imho вручную будет намного более читабельным и более важным.

Вот пример:

$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

Спасибо, это именно то, что я искал! –

+0

Это работало очень хорошо для меня. И мне нравится создавать и читать XML-файлы более естественным образом, как вы указали. – rrirower

+0

Написано как функция (и, вероятно, лучше подходит для пространств имен?) По адресу https://gist.github.com/thoemmi/2937183 –

1

Проверить этот пример кода. У этого есть все, что вам нужно для создания XML из краха:

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)