如何仅导入父节点使用PowerShell从xml文件中保留所有子节点?

时间:2017-07-21 10:09:46

标签: xml powershell xml-parsing

我有一个像这样的xml文件

  <parent>
  <child1>
    <subchild11/>
    <subchild12/>
   </child1>
   <child2>
    <subchild21/>
    <subchild22/>
   </child2>
  </parent>

我想只导入没有子节点的父节点(带参数,如果有的话)。然后我想用这个父节点创建一个新的xml,并将child添加到我的愿望中。 我不想使用CreateNode()创建父节点。

有可能吗?我无法在任何地方找到它。

2 个答案:

答案 0 :(得分:1)

您可以导入XML,然后从父节点中删除所有子项。

$xmlDocument = [Xml](Get-Content 'file.xml')
$parent = $xmlDocument.ChildNodes[0]
# Remove all children
while ($parent.FirstChild -ne $null) {
     $parent.RemoveChild($parent.FirstChild)
}

然后,您可以添加子项:

# Add new child nodes
$parent.AppendChild(...)
$parent.AppendChild(...)

修改$parent.RemoveAll()也会移除父级的属性(非常令人困惑,我必须承认),因此我将其替换为循环以删除所有子级。

答案 1 :(得分:0)

另一种方法使用ImportNode的第三个参数,称为“ deep”。设置为$ true会复制所有后代节点,但设置为$ false只会复制属性。请参阅Microsoft开发人员网络页面 https://msdn.microsoft.com/en-us/library/system.xml.xmldocument.importnode(v=vs.110).aspx

当输入为DocumentElement且“ deep”为$ true

  

source元素的后代及其指定的属性   递归地导入节点,并将结果节点重组为   形成相应的子树。

     

注意:不复制默认属性。如果文件被   导入到定义此元素名称的默认属性,即那些   被分配。

当“ deep”为$ false时,

  

导入源元素的指定属性节点,并且   生成的XmlAttribute节点附加到生成的XmlElement。

     

注意:不复制默认属性。如果文件被   导入到定义此元素名称的默认属性,即那些   被分配。

以下代码展示了这种方法的实际作用:

$inxml = [xml] @"
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="myfile.xsl" ?>
<bookstore specialty="novel">
  <book style="autobiography">
    <author>
      <first-name>Joe</first-name>
      <last-name>Bob</last-name>
      <award>Trenton Literary Review Honorable Mention</award>
    </author>
    <price>12</price>
  </book>
  <book style="textbook">
    <author>
      <first-name>Mary</first-name>
      <last-name>Bob</last-name>
      <publication>Selected Short Stories of
        <first-name>Mary</first-name>
        <last-name>Bob</last-name>
      </publication>
    </author>
    <editor>
      <first-name>Britney</first-name>
      <last-name>Bob</last-name>
    </editor>
    <price>55</price>
  </book>
</bookstore>
"@

$outxml1 = New-Object -TypeName System.Xml.XmlDocument
$outxml2 = New-Object -TypeName System.Xml.XmlDocument

$inxml.bookstore

# third parameter of ImportNode is $true for 'deep copy'
# where descendants are copied fully
# see https://msdn.microsoft.com/en-us/library/system.xml.xmldocument.importnode(v=vs.110).aspx
# The descendants of the source element and its specified
# attribute nodes are recursively imported and the resulting
# nodes reassembled to form the corresponding subtree.
$outnode1 = $outxml1.ImportNode($inxml.bookstore, $true)
$outxml1.AppendChild($outnode1)
$outxml1
$outxml1.Save("N:\temp\xml_desc.xml")

# third parameter of ImportNode is $false for "not a 'deep copy'"
# from the above reference:
# Specified attribute nodes of the source element are imported, 
# and the generated XmlAttribute nodes are attached to the 
# generated XmlElement.
$outnode2 = $outxml2.ImportNode($inxml.bookstore, $false)
$outxml2.AppendChild($outnode2)
$outxml2
$outxml2.Save("N:\temp\xml_nodesc.xml")

Write-Host "Ends"

输出文件xml_desc.xml是:

<bookstore specialty="novel">
  <book style="autobiography">
    <author>
      <first-name>Joe</first-name>
      <last-name>Bob</last-name>
      <award>Trenton Literary Review Honorable Mention</award>
    </author>
    <price>12</price>
  </book>
  <book style="textbook">
    <author>
      <first-name>Mary</first-name>
      <last-name>Bob</last-name>
      <publication>Selected Short Stories of
    <first-name>Mary</first-name><last-name>Bob</last-name></publication>
    </author>
    <editor>
      <first-name>Britney</first-name>
      <last-name>Bob</last-name>
    </editor>
    <price>55</price>
  </book>
</bookstore>

而xml_nodesc.xml是:

<bookstore specialty="novel" />

这似乎可以满足OP的要求。

我希望这对某人有帮助,即使为OP提供帮助也为时已晚。