在PowerShell中将XML转换为CSV时,是否有方法将水平格式的CSV输出转换为垂直格式?

doinxwow  于 2023-06-23  发布在  Shell
关注(0)|答案(1)|浏览(156)

我有一个XML,我转换为CSV,它工作正常,并输出行到CSV。我想格式化的csv垂直与水平。

$xml = [xml](Get-Content "C:\temp\test.xml")
$data = $xml.SelectNodes("//EmployeeImport/Employee") | Select-Object -Property *
$data | Export-Csv -Path "c:\temp\employee.csv" -NoTypeInformation 
$csvFile = "c:\temp\employee.csv"
$folderPath = Split-Path -Parent $csvFile
$csv = Import-Csv -Path $csvFile -Delimiter "," 

foreach ($record in $csv) {
    $OutFileName = join-path -Path $folderPath -ChildPath $($record.FirstName + " " + $record.LastName  +  $record.HireDate.replace('/','_') + ".csv");
    $record | select-object * | export-csv -NoTypeInformation -Path $OutFileName -Delimiter ",";
}

电流输出
| 姓名|社会|
| - -----|- -----|
| 米奇|123456|
期望输出
| 姓名|米奇|
| - -----|- -----|
| 社会|123456|

bnl4lu3b

bnl4lu3b1#

这个Join-Object Module基本上意味着基于相关属性连接两个对象列表(另请参见:In Powershell, what's the best way to join two tables into one?,但它也可以用于进行并行连接(通过省略-on参数定义的相关属性)。这对于转置表是有用的,例如csv文件:

Install-Module -Name JoinModule -MinimumVersion 3.8.1

样本Csv

$Csv = @'
"@","A","B","C"
"1","D","E","F"
"2","G","H","I"
"3","J","K","L"
'@

作为矩阵

考虑一个Csv文件(或字符串)作为一个矩阵,其中标题行具有与每个后续数据行相同的格式,您可能只需用逗号分隔符分隔每个字段:

$Table = @()
# Get-Content .\My.csv |Foreach-Object { ...
$Csv -Split '\r?\n' |Foreach-Object { $Table = $Table |FullJoin $_.Split(',') }
$Transposed = $Table |Foreach-Object { $_ -Join ',' }

说明

  • $Csv -Split '\r?\n'将多行字符串拆分为行数组,这是Get-Content cmdlet的默认行为
    • 注意:* 此方法不考虑数据可能还包含逗号,例如:

"Name","Social"
"Mickey","123,456"

  • $Table = $Table |FullJoin $_.Split(',')将每行作为一列连接到前一行,并输出PSObject集合列表(System.Collections.ObjectModel.Collection[psobject]]),类似于foreachwhere方法
    • 注意:* Join-Object cmdlet的3.8.1之前的版本中存在错误,无法正确实现从空管道($Table = @())开始
  • $Table |Foreach-Object { $_ -Join ',' }遍历PSObject集合的每一行,并将每个项目(使用-join * 运算符 *)连接为单个字符串。

作为PowerShell对象列表

$Data = ConvertFrom-Csv $Csv # = $xml.SelectNodes("//EmployeeImport/Employee")
$Names = $Data[0].PSObject.Properties.Name
$Last = $Names.get_Count() - 1
$Table = @() |FullJoin $Names[1..$Last] -Name $Names[0]
$Data |Foreach-Object {
    $Values = $_.PSObject.Properties.Value
    $Last = $Values.get_Count() - 1
    $Table =  $Table |FullJoin $Values[1..$Last] -Name $Values[0]
}

说明

在这种情况下,输入被认为包含PowerShell对象的列表。通常每行都是一个PowerShell对象,对象中的每个属性表示一列。

  • 这意味着标题行实际上包含在$Data[0].PSObject.Properties.Name中的第一行(以及所有其他行)中。
  • 重新生成输出的计数相同,其中第一项应被视为每个对象的属性名。这是通过命令完成的:... |FullJoin $Names[1..$Last] -Name $Names[0]

相关问题