2012-07-15 29 views
3

我是一名PowerShell和XPath初學者,他們努力通過某些XML高效地解析並構建用於進一步處理(例如CSV輸出,SQL Server加載)的對象數組。下面包含了一個XML樣本以及我目前使用的代碼片段。在此架構中,每個object-array表示所需輸出中的單個行。我正在解析MetaData子項以獲取專欄的專有名稱,然後構建一組PSObject,其中數組中的每個對象表示一行。信息MetaData用於查找列名稱(PSObject屬性)。將大型XML文件解析爲PowerShell對象

這適用於10K行左右的文件,但對超過500K行的最大文件運行時可能會非常糟糕。在這些情況下,每行需要大約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 { 
    [email protected]{} 

    #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) 

回答

0

你可以得到的元數據名稱無需在每個itreation重新創建ColumnHeaders:

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

同適用於$ collection。代碼的最終結果如何?

UPDATE:試試這個

[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 
+0

'$ obj.Report.Data.Columns.MetaData.Name'返回任何內容,而'$ obj.Report.Data.Columns.MetaData | gm'顯示我回到名爲屬性關聯的XMLElements。最終的結果是一個數組'$ collection'的對象,然後可以通過管道輸出到csv,ft或其他PS處理。 – 2012-07-15 14:33:16

+0

您可以包含示例輸出嗎? – 2012-07-15 15:15:48

+0

輸出是PSObjects的集合,其屬性對應於對應於行(對象數組)的列標題和值。在示例XML中,結果將是具有以下屬性/值對的單個對象:Column1 =「Column1 Value」,Column2 =「Column2 Value」,Column3 =「Column3 Value」。在處理實時數據的情況下,將會有一個包含10,000-500,000個這些對象的PS數組,然後可以將它們轉移到export-csv,SQL Server加載的數據集或在PS中進一步處理。 – 2012-07-15 15:31:18