4

私は PowerShell と XPath の初心者で、いくつかの XML を効率的に解析し、さらなる処理 (CSV 出力、SQL Server の読み込みなど) のためにオブジェクトの配列を構築するのに苦労しています。XML のサンプルと、私が現在使用しているコード スニペットを以下に示します。このスキーマでは、それぞれobject-arrayが目的の出力の 1 つの行を表します。子を解析しMetaDataて列の適切な名前を取得し、配列内の各オブジェクトが単一の行を表す PSObjects のコレクションを構築しています。このMetaData情報は、列名 (PSObject プロパティ) を見つけるために使用されます。

これは、10,000 行程度のファイルでは問題なく機能しますが、500,000 行を超える最大のファイルに対して実行すると、ひどく動きが鈍くなります。このような場合、各行の処理に約 3 ~ 4 秒かかります。500K 行では、実行に時間がかかります。これを高速化するために使用できる XPath または PS 変数の割り当てに関する魔法はありますか?

すぐに必要なのは、この XML を CSV に変換することです (現在は を介し​​て実行されますexport-csv)。ただし、次にこのデータを SQL Server にロードすることを検討するため、スクリプトのこの部分でオブジェクトのコレクションを生成することをお勧めします。インスタンスまたは他の処理を行います。

助けてくれてありがとう!

デビッド

サンプル XML

<Report>
<Data>
<Columns>
<MetaData>
<Index>0</Index>
<Name>Column1</Name>
<Index>1</Index>
<Name>Column2</Name>
<Index>2</Index>
<Name>Column3</Name>
</MetaData>
</Columns>
<Rows>
<object-array>
<string>column1 value</string>
<int>column2 value</string>
<string>column3 value</string>
</object-array>
</Rows>
</Data>
</Report>

サンプルコード

#extract the column headers
[string[]]$ColumnHeaders = @()
$obj.SelectNodes("/Report/Data/Columns/MetaData") |% {$ColumnHeaders += $_.name}

$collection = @()
$rowint = 0
$rowcount = $obj.Report.Data.Rows."object-array".count

#unwind the rows
do {
    $hash=@{}

    #loop through each element in the row parent element and add it to the hash
    $columnint = 0
    $columncount = (Select-Xml -xPath "Report/Data/Rows/object-array[$rowint]/node()" $obj).count
        do {
            $hash.Add($columnheaders[$columnint], (Select-Xml -xPath "Report/Data/Rows/object-array[$rowint]/descendant::text()[$columnint]" $obj).Node.Value)
            $columnint++
        } while ($columnint -lt $columncount)


    $thisrow = New-Object PSObject -Property $hash 

    #add this new row to the collection 
    $collection += $thisrow 
    $rowint++
} while ($rowint -lt $rowcount)
4

1 に答える 1

1

各反復で ColumnHeaders を再作成せずに MetaData 名を取得できます。

$ColumnHeaders = $obj.Report.Data.Columns.MetaData.Name

同じことが $collection にも当てはまります。コードの最終結果はどのようになりますか?

更新:これを試してみてください

[xml]$obj = Get-Content test.xml

$data = $obj.Report.Data

$pso = New-Object PSObject
$pso | Add-Member NoteProperty -Name $data.Columns.MetaData.Name[0] -Value $data.Rows.'object-array'.string[0]
$pso | Add-Member NoteProperty -Name $data.Columns.MetaData.Name[1] -Value $data.Rows.'object-array'.int
$pso | Add-Member NoteProperty -Name $data.Columns.MetaData.Name[2] -Value $data.Rows.'object-array'.string[1] -PassThru
于 2012-07-15T13:41:33.593 に答える