4

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

这适用于大约 10K 行的文件,但在运行超过 500K 行的最大文件时会严重陷入困境。在这些情况下,每行大约需要 3-4 秒来处理。在 500K 行时,运行时间很长。我可以使用 XPath 或 PS 变量赋值来加快速度吗?

迫切需要将此 XML 转换为 CSV(当前export-csv通过实例或做其他处理。

谢谢您的帮助!

大卫

示例 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 回答