31

使用 PowerShell,我想将几​​个子元素添加到 XML 树中。
我知道添加一个元素,我知道添加一个或多个属性,但我不明白如何添加几个元素。

一种方法是将子 XML 树编写为文本
但我不能使用这种方法,因为元素不是一次添加的。

要添加一个元素,我这样做:

[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
  ]

问题:如何一次添加多个子元素?

4

4 回答 4

46

看看下面的例子:

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

已编辑

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

于 2012-06-12T06:34:16.517 回答
37

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)
于 2015-04-17T08:04:51.137 回答
5

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>
于 2015-09-13T08:13:16.233 回答
0

For anyone else visiting this.

I had issues because my parent document had a namespace, and the ImportNode was adding an empty xmnls="" element to the imported xml, causing issues with my app

Extending on answer above. To get around this, wrap it in a dummy node, with namespace set from parent doc

$pathToConfig = $env:windir + "\Microsoft.NET\Framework64\v4.0.30319\Config\web.config"

$xml = [xml] (type $pathToConfig)
$root = $xml.get_DocumentElement()
$namespaceuri = $root.NamespaceURI

[xml]$appSettingsXml = @"
<Dummy xmlns="$namespaceuri">
    <appSettings>
        <add key="WebMachineIdentifier" value="$webIdentifier" />
    </appSettings>
</Dummy>
"@


$xml.configuration.AppendChild($xml.ImportNode($appSettingsXml.Dummy.appSettings, $true))
$xml.Save($pathToConfig)
于 2021-05-18T04:59:13.333 回答