2012-04-23 5 views
1

私はいくつかのXMLをソートしており、特定の固有でない要素を並べ替えることを希望しています。属性を使用すると、類似要素をグループ化できます。これらのグループ内では、私は元の順序を維持する必要があります。問題は、並べ替えるとき、これらのグループ内の順序が変更され、並べ替えると順序がもう一度変わるということです。私は、XMLの内容が変更されていなければ(もしそうでなければSVN diffsが醜い)ものを変更しないソートが必要です。ここでは簡単な例である:ここでは順序を変更するPowerShellのSort-Objectコマンドレットw.r.t.属性がソートされていない

$xml = [xml]@" 
<root> 
    <element name="a" number="1" /> 
    <element name="b" number="1" /> 
    <element name="c" number="1" /> 
    <element name="d" number="2" /> 
    <element name="e" number="2" /> 
    <element name="f" number="2" /> 
    <element name="g" number="3" /> 
    <element name="h" number="3" /> 
</root> 
"@ 

Write-Host "`nFirst Sort produces this:" 
$result1 = $xml.SelectNodes('//element') | Sort-Object -Property 'number' 
Write-Host (($result1 | select -ExpandProperty 'number') + " <---Sorted on") 
Write-Host (($result1 | select -ExpandProperty 'name') + " <---Order not maintained") 

Write-Host "`nSorting the (already sorted) results of First Sort produces this:" 
$result2 = $result1 | Sort-Object -Property 'number' 
Write-Host (($result2 | select -ExpandProperty 'number') + " <---Sorted on") 
Write-Host (($result2 | select -ExpandProperty 'name') + " <---Order changed again") 

が出力されます。この例では

First Sort produces this: 
1 1 1 2 2 2 3 3 <---Sorted on 
c b a f e d h g <---Order not maintained 

Sorting the (already sorted) results of First Sort produces this: 
1 1 1 2 2 2 3 3 <---Sorted on 
a b c d e f g h <---Order changed again 

、私は「番号グループ」内のオリジナル「名前」順序を保存する必要があります。

を簡単にこれを元の順序を維持し、複数回ソートするときに出てくる方法はありますか?

元の順序を表すダミー属性の追加を避けようとしています。おそらく、より決定論的な別の.NETソート関数があるでしょうか?私は検索しましたが、同等のグループ内での注文には関係していないようでした。

ありがとうございました。特性の両方に関して

+0

の構文を追加しましたか?たとえば、「ソートオブジェクト番号、名前」 –

+0

残念ながら、元の順序を保持するために必要なものはありません(これらの順序は人間の意味です。これらは人が読んだ/編集するソースファイルです)。良い質問。 – Vimes

+0

'Sort-Object'のドキュメントは安定した並べ替えを使用している場所を示していないので、それを期待する理由はありません。 – Joey

答えて

1

すでに自然なソート順を表して何かを持っていない場合、あなただけ追加することができますAdd-Memberを持つインデックスプロパティ:

$nodes = @($xml.SelectNodes('//element')) 
for ($i=0; $i -lt $nodes.Count; $i++) 
{ 
    $nodes[$i] = $nodes[$i] | Add-Member -MemberType NoteProperty "Index" $i -PassThru 
} 

$result1 = $nodes | Sort-Object name, Index 

次に、同じまたはあなたが何回並べ替えをしても、いつでもどこでも行けます。

更新:これは直接あなたの質問に答えるが、あなただけのソートに複数のプロパティができていないのPowerShell v2の

+0

私はそれがおそらく私ができることだと思います。私は属性を追加しないことを望んでいましたが、元の順序を保持する標準的なソートメカニズムはないかもしれません。私は今週それを打つつもり、答えをマークします。 :) – Vimes

+0

ええと、私は、System.Xml.XmlElement型で動作するAdd-Memberを取得できません。新しいメンバーを受け取ることはありません。ヘルプ記事によれば、Add-Memberは「Windows PowerShellオブジェクトのインスタンス」で動作します。これは、任意の.NETオブジェクトは含まれていないと思いますか?私は本当にあいまいな名前でXML属性を使用する必要がありますね。ハックですが、うまくいくはずです。 – Vimes

+0

おっと、私はPowerShell v3プレビューでのみテストしました!どうやら、v3はそれがリスト処理で少しリベラルなものです。 $ xml.SelectNodesの周りに "@()"を追加して、結果をPowerShellリストとして解釈することができます。 –

0

並べ替え:

$xml.SelectNodes('//element') | Sort-Object -Property number, name 

これは、この出力を生成します

name  number 
----  ------ 
a  1 
b  1 
c  1 
d  2 
e  2 
f  2 
g  3 
h  3 
+0

残念ながら、サンプルのようにアルファベットではない可能性があるname属性を元の順序に保つ必要があります。 – Vimes

関連する問題