2012-06-11 97 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树(partialy显示):

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​​来逐个构建节点,因为手工制作它会更具可读性和更可维护性。

下面是一个例子:

$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

检查这代码采样。它拥有您从Cratch创建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)