powershell xml 排序节点和替换子节点 [英] powershell xml sort nodes and replacechild

查看:63
本文介绍了powershell xml 排序节点和替换子节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试用 powershell 和 xml 做一些非常简单的事情,但没有一点麻烦.基本上我正在尝试采用以下 xml... 并按名称对机器元素进行排序.然后将它们放回 XML 中,以便我可以保存回文件.

I'm trying to do something pretty simple with powershell and xml but haven't a bit of trouble. Basically I'm trying to take the following xml... and sort the machine elements by name. Then put them back into the XML so that I can save back to a file.

如果输出 $new 对象,排序似乎有效,但是在替换子对象期间,它抱怨无法转换参数0",值为:System.Object[]",ReplaceChild"键入System.Xml".XmlNode" : "无法将 "System.Object[]" 转换为类型 "System.Xml.XmlNode".

Sorting seems to be working if output the $new object however, during the replacechild it's complaining "Cannot convert argument "0", with value: "System.Object[]" for "ReplaceChild" to type "System.Xml.XmlNode" : "Cannot convert the "System.Object[]" to type "System.Xml.XmlNode".

如果我在 $orig 和 $new 上都执行 Get-Member,它们都说它们属于 XMLElement 类型,我相信它继承自 XMLNode.

If I do a Get-Member on both $orig and $new they both say they are of type XMLElement which I believe inherits from XMLNode.

我错过了什么家伙?使我抓狂.感谢您的帮助!

What am I missing guys? Driving me nuts. Thanks for your help!

<company>
    <stuff>
    </stuff>
    <machines>
        <machine>
            <name>ca</name>
            <b>123</b>
            <c>123</c>
        </machine>
        <machine>
            <name>ad</name>
            <b>234</b>
            <c>234</c>
        </machine>
        <machine>
            <name>be</name>
            <b>345</b>
            <c>345</c>
        </machine>
    </machines>
    <otherstuff>
    </otherstuff>
</company>

[xml]$xml = (get-content Company.xml)
[XmlNode]$orig = $xml.Company.Machines
[XmlNode]$new = ($orig.Machine | sort Name )
$xml.Company.ReplaceChild($new, $orig)

推荐答案

这里有各种各样的问题.一个是您的 sort 返回一个 xml 元素列表而不是单个 xml 元素.另一个问题是它返回原始 xml 元素而不是副本,因此您使用它们对 xml DOM 进行的任何操作也会影响结果.

There are various problems here. One is that your sort returns a list of xml elements rather than a single xml element. Another problem is that it returns the original xml elements rather than copies, so any manipulation of the xml DOM that you do using them will also affect the result.

这是获得所需内容的简单方法.按倒序排序,然后将每个节点依次插入到其他节点的前面.每次从排序结果中插入一个节点时,它会自动将其从原始节点集中删除:

Here's a simple way to get what you want. Sort in reverse order, and then insert each node in turn in front of the others. Each time you insert a node from the result of the sort it will automatically remove it from the original set of node:

[xml]$xml = @"
<company>
    <stuff>
    </stuff>
    <machines>
        <machine>
            <name>ca</name>
            <b>123</b>
            <c>123</c>
        </machine>
        <machine>
            <name>ad</name>
            <b>234</b>
            <c>234</c>
        </machine>
        <machine>
            <name>be</name>
            <b>345</b>
            <c>345</c>
        </machine>
    </machines>
    <otherstuff>
    </otherstuff>
</company>
"@
[System.Xml.XmlNode]$orig = $xml.Company.Machines
$orig.Machine | sort Name  -Descending |
  foreach { [void]$xml.company.machines.PrependChild($_) }
$xml.company.machines.machine

管道也可以用升序编写(正如大卫马丁指出的那样),您可以通过使用变量中的节点来减少输入:

The pipeline can also be written with an ascending sort (as David Martin pointed out), and you can reduce typing by using the node in the variable:

$orig.Machine | sort Name | % { [void]$orig.AppendChild($_) }

这篇关于powershell xml 排序节点和替换子节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆