我正在尝试将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
}
有数据-但作为每条记录的一个属性
答案 0 :(得分: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
希望这会有所帮助。
答案 1 :(得分:0)
Greg的(出色)解决方案使用字符串拼接来创建原型CSV文件(在$ csv中),然后将其转换回powershell集合,然后将其转换为CSV作为清理阶段。字符串拼接方法不是很复杂,如果输入数据包含被视为CSV元数据(即逗号)的东西,则事情会变得混乱。因此,我发现使用制表符char更安全:
$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
这并不完全可靠,但对我来说足够好了。