将大型XML文件解析为PowerShell对象

时间:2012-07-15 13:05:27

标签: powershell xml-parsing

我是PowerShell和XPath的初学者,正在努力有效地解析一些XML并构建一个对象数组以进行进一步处理(例如CSV输出,SQL Server加载)。下面包含XML示例以及我当前使用的代码段。在此架构中,每个object-array表示所需输出中的单个行。我正在解析MetaData子项以获取列的正确名称,然后构建PSObject集合,其中数组中的每个对象代表一行。 MetaData信息用于查找列名称(PSObject属性)。

这适用于行数为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 {
    $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)

1 个答案:

答案 0 :(得分:0)

您可以获取MetaData名称,而无需在每个itreation中重新创建ColumnHeaders:

$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