【问题标题】:Struggling with Powershell XML to CSV努力将 Powershell XML 转换为 CSV
【发布时间】:2018-06-25 13:53:05
【问题描述】:

我正在尝试将 XML 文件转换为 CSV。虽然question here 很有用,但我无法将这些建议应用到我的案例中——大概是因为我的实体是多值的。我的 Xml 看起来像:

<?xml version="1.0" encoding="UTF-8">
<ReportOutput Version="1">
  <ReportFilters>
    <Filter Name="Report Name" Value="My report"/>
    <Filter Name="Path" Value="/">
    <Filter Name="attr1" Value="*">
    ...
  </ReportFilters>
  <ReportHeader>
    <columnHeader>attr1</columnheader>
    <columnHeader>attr2</columnheader>
    <columnHeader>attr3</columnheader>
    ...
  </ReportHeader>
  <ReportRecord>
    <item>1</item>
    <item>first</item>
    <item>A</item>
    ...
  </ReportRecord>
  <ReportRecord>
    <item>2</item
    <item>second</item>
    <item>B</item>
    ...
  </ReportRecord>
  ...
</ReportOutput>
(where '...' represents one or recurrences of the previous node pattern)

XML 只是对本质上是表格数据集的东西的薄包装 - ReportHeader 和 ReportRecord 节点都包含相同数量的子节点。

我想要 CSV 文件中的 ReportHeader.columnHeaders 和 ReportRecord.Items:

attr1, attr2, attr3 ...
1, first, A ...
2, second, B ...

我可以很容易地删除ReportFilters:

[xml]$xml = Get-Content data.xml

$filter=$xml.ReportOutput.ReportFilters
$filter.ParentNode.RemoveChild($filter)

但遍历数据有点棘手。

$xml.ReportOutput.ChildNodes | Export-Csv "C:\Temp\report.csv" -NoTypeInformation -Delimiter:"," -Encoding:UTF8

CSV 文件中的第一条记录是单个属性'"columnHeader"',第二条记录是'"System.Object[]"' 之后,很多空行。

 {
    $xml.ReportOutput.ReportHeader | ConvertTo-Csv -NoTypeInformation -Delimiter:","
    foreach ($r in $xml.ReportRecord) {
    $r | ConvertTo-Csv -NoTypeInformation -Delimiter:","
    }
} | Set-Content -Path "C:\Temp\report.csv" -Encoding:UTF8

将部分源代码写入输出流。

 $xml.ReportOutput.ReportHeader | ConvertTo-Csv -NoTypeInformation -Delimiter:"," | Set-Content -Path "C:\Temp\report.csv" -Encoding:UTF8
 foreach ($r in $xml.ReportOutput.ReportRecord) {
    $r | ConvertTo-Csv -NoTypeInformation -Delimiter:"," | Add-Content -Path "C:\Temp\report.csv" -Encoding:UTF8
 }

只是写了很多废话。

 $xml.ReportOutput.ReportHeader.ChildNodes | ConvertTo-Csv -NoTypeInformation -Delimiter:"," | Set-Content -Path "C:\Temp\report.csv" -Encoding:UTF8
 foreach ($r in $xml.ReportOutput.ReportRecord) {
    $r.ChildNodes | ConvertTo-Csv -NoTypeInformation -Delimiter:"," | Add-Content -Path "C:\Temp\report.csv" -Encoding:UTF8
 }

有数据 - 但作为每条记录的一个属性

【问题讨论】:

    标签: xml powershell


    【解决方案1】:

    我真诚地相信您的 XML 文档是有效的,并且其中的所有结束标记都是正确的(作为提示)。所以...

    # create header of the future CSV (attr1,attr2,attr3...)
    $csv = @(($xml = [xml](Get-Content C:\path\input.xml)).SelectNodes('//columnHeader').'#text' -join ',')
    # append lines to the future CSV
    $csv += $xml.SelectNodes('//ReportRecord').ForEach{$_.item -join ','}
    # at present moment $csv is the array
    # attr1,attr2,attr3...
    # 1,first,A...
    # 2,second,B...
    # time to write this data as CSV on disk
    $csv | ConvertFrom-Csv | Export-Csv C:\path\output.csv
    

    希望这会有所帮助。

    【讨论】:

    • ...几乎。在别处查看其他答案。
    【解决方案2】:

    Greg 的(优秀)解决方案使用字符串拼接创建原型 CSV 文件(在 $csv 中),然后将其转换回 powershell 集合,然后转换为 CSV 作为清理阶段。字符串拼接方法不是很复杂,如果输入数据包含被视为 CSV 元数据(即逗号)的东西,事情就会变得混乱。因此,我发现使用制表符更安全:

    $csv = @(($xml = [xml](Get-Content C:\path\input.xml)).SelectNodes('//columnHeader').'#text' -join "`t")
    $csv += $xml.SelectNodes('//ReportRecord').ForEach{$_.item -join "`t"}
    $csv | ConvertFrom-Csv -Delimiter "`t" | Export-Csv C:\path\output.csv
    

    这并不完全强大,但对我来说已经足够了。

    【讨论】:

      猜你喜欢
      • 2017-09-09
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      • 2020-06-10
      • 1970-01-01
      • 2019-12-11
      • 1970-01-01
      • 2023-02-05
      相关资源
      最近更新 更多