简体   繁体   English

添加 XML 子元素

[英]adding XML sub-elements

With PowerShell, I want to add several sub-elements into an XML tree.使用 PowerShell,我想将几​​个子元素添加到 XML 树中。
I know to ADD ONE element, I know to add one or several attributes, but I don't understand how to ADD SEVERAL elements.我知道添加一个元素,我知道添加一个或多个属性,但我不明白如何添加多个元素。

One way whould be to write a sub-XML tree as text一种方法是将子 XML 树编写为文本
But I can't use this method because the elements are not added at once.但是我不能使用这种方法,因为元素不是一次添加的。

To add one element, I do that:要添加一个元素,我这样做:

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

Works fine.工作正常。 This give me this XML tree:这给了我这个 XML 树:

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

Now I want to add a sub element to 'my_element'.现在我想向“my_element”添加一个子元素。 I use a similar method:我使用类似的方法:

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

This give this XML tree (partialy displayed):这给出了这个 XML 树(部分显示):

my_element =
  class XmlElement
  {
    my_sub_element =
    another_one =
  }

Those are attributes, not sub-elements.这些是属性,而不是子元素。
Sub-elements would be displayed as this:子元素将显示为:

my_element =
  [
    my_sub_element
    another_one
  ]

Question : How do I add several sub-elements, one at a time?问题:如何一次添加多个子元素?

Have a look to the following example :看看下面的例子:

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

Edited已编辑

Remark : Using a relative path in Save will not do what you expect .备注: 在 Save 中使用相对路径不会达到您的预期

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.我更喜欢手动创建 xml,而不是使用 API 逐个节点地构建它,因为 imho 手动它将更具可读性和更易于维护。

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)

Check this code-sample.检查此代码示例。 It has everything you need to create XML from scratch:它拥有从头开始创建 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()
}

...now let's use both functions to create and display a new XML-object: ...现在让我们使用这两个函数来创建和显示一个新的 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)

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>

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我遇到了问题,因为我的父文档有一个命名空间,而ImportNode正在向导入的 xml 添加一个空的xmnls=""元素,导致我的应用程序出现问题

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM