Powershell xml sorts nodes and replaces

I am trying to do something pretty simple with powershell and xml, but I have no problem. Basically I am trying to take the following xml ... and sort the elements of the machine by name. Then return them to XML so that I can save it back to the file.

Sorting seems to work if a new $ object is displayed, however during replacechild it complains: "It is not possible to convert the argument" 0 "with the value:" System.Object [] "to" ReplaceChild "to type" System.Xml. "XmlNode ":" Cannot convert "System.Object []" to type "System.Xml.XmlNode".

If I do a Get-Member for both $ orig and $ new, they both say they are of type XMLElement, which I assume is inherited from XMLNode.

What do I miss guys with? Drives me crazy. Thank you 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)
+3
source share
3 answers

There are various problems here. First, your sortreturns a list of xml elements, not a single xml element. Another problem is that it returns the original xml elements, not copies, so any manipulations with the xml DOM that you use with them also affect the result.

Here is an easy way to get what you want. Sort in reverse order, and then paste each node in turn in front of the others. Each time you insert a node from the sort result, it automatically removes it from the original node set:

[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

: ( ), node :

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

Duncan robert.westerlund , xml-, :

[xml]$xml = @"
<config>
    <namespace name='Some namespace'>
        <settings>
            <setting name='c setting' />
            <setting name='a setting' />
            <setting name='b setting' />
        </settings>
        <namespace name='Child namespace'>
            <settings>
                <setting name='z setting' />
                <setting name='y setting' />
                <setting name='x setting' />
            </settings>
        </namespace>
    </namespace>
</config>
"@

#[xml]$xml = Get-Content "PATH_TO_SOME_FILE.xml"

$xml.SelectNodes("//namespace/settings") | % { 
    $parentNode = $_; $_.Setting | Sort-Object -Property name | % { 
        $parentNode.AppendChild($_) | Out-Null
    } 
}

$xml.Save("PATH_TO_SOME_FILE.xml")

settings node xml, .

+2

, , , $xml.Company.Machines - XmlElement. , $xml.Company.Machines.Machine, , .

ReplaceChild , , , , . - :

[xml]$xml = Get-Content .\Company.xml
$machines = $xml.company.machines
$orderedMachineCollection = $machines.machine | Sort Name
$machines.RemoveAll()
$orderedMachineCollection | foreach { $machines.AppendChild($_) } | Out-Null
+1

All Articles