如何使用PowerShell 2.0将此XML转换为CSV?

时间:2014-05-01 14:02:11

标签: xml powershell csv

我尝试使用PowerShell 2.0将以下XML转换为CSV,我可以获取一些数据,但在尝试浏览XML对象时,我似乎无法获得数据一种格式,可以让我做一个好桌子。

我拥有的是这样的东西,有多个项目

  1. <root type="array">   
      <item type="object">
        <short_version type="string">11</short_version>
        <long_name type="string">Internet Explorer</long_name>
        <api_name type="string">internet explorer</api_name>
        <long_version type="string">11.0.9600.16384.</long_version>
        <latest_stable_version type="string"></latest_stable_version>
        <automation_backend type="string">webdriver</automation_backend>
        <os type="string">Windows 2012 R2</os>
      </item>
      ... 
    </root>
    
  2. 我最终得到了Type,或者如果我尝试访问InnerHTML,我只得到值,但是在长字符串中。

    我到目前为止:

    [xml]$convertMe = Get-Content $jsonTemp
    $convertMe.SelectNodes("//item") | % { $_.InnerText }
    

    如何以漂亮的CSV格式获取此内容,如:

      

    SHORT_VERSION,LONG_NAME,API_NAME,long_version,latest_stable_version,automation_backend,OS   11,Internet Explorer,Internet Explorer,11.0.9600.16384 ,, webdriver,Windows 2012 R2

3 个答案:

答案 0 :(得分:3)

这是一个硬编码且很长的解决方案,但它确实有效。 :)尝试:

$xml = [xml](Get-Content .\test.xml)

$xml.root.item | Select-Object @(
@{l="short_version";e={$_.short_version."#text"}},
@{l="long_name";e={$_.long_name."#text"}},
@{l="api_name";e={$_.api_name."#text"}},
@{l="long_version";e={$_.long_version."#text"}},
@{l="latest_stable_version";e={$_.latest_stable_version."#text"}},
@{l="automation_backend";e={$_.automation_backend."#text"}},
@{l="os";e={$_.os."#text"}}) |
Export-Csv test.csv -NoTypeInformation

test.csv

"short_version","long_name","api_name","long_version","latest_stable_version","automation_backend","os"
"11","Internet Explorer","internet explorer","11.0.9600.16384.",,"webdriver","Windows 2012 R2"

另类且可能更慢的解决方案:

$xml = [xml](Get-Content .\test.xml)

#Foreach item
$xml.root.item | ForEach-Object {
    $obj = New-Object psobject
    $_.GetEnumerator() | ForEach-Object {
        #Get all properties/elements and values
        $obj | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_.InnerText
    }
    $obj
} |
#Set property order. This also makes sure that all items exports the same properties(which a csv needs)
Select-Object short_version,long_name,api_name,long_version,latest_stable_version,automation_backend,os |
#Export to csv
Export-Csv test.csv -NoTypeInformation

答案 1 :(得分:1)

它可能有点乱,但它可以让你完全找到你正在寻找的东西。

[xml]$convertMe = Get-Content $jsonTemp
[Array]$MeConverted = $convertMe.GetElementsByTagName('item')
$Collection = @()
ForEach($Record in $MeConverted){
    $Output = new-object psobject
    $Record.selectnodes("*")|%{Add-Member -InputObject $Output -MemberType NoteProperty -Name $_.Name -Value $_.'#text'}
    If($Collection){
        $T2Keys = $Collection|gm|?{$_.MemberType -match "Property"}|Select -ExpandProperty Name
        $T1Keys = $Output|gm|?{$_.MemberType -match "Property"}|Select -ExpandProperty Name
        $KeysToAdd = $T2Keys|?{$T1Keys -notcontains $_}
        $KeysToAdd|%{$Collection|Add-Member $_ ""}
    }
    $Collection += $Output
}
$Collection | Export-CSV file.csv -notype

编辑:在我看来,Frode的看起来更清晰,但我的确有一个好处,就是不必了解所有的子节点&#39;名。

编辑2:修复了明显的瑕疵,显然会有多个项目,我完全没有考虑到这一点。这只是让我的代码更大,因为我需要考虑其他潜在的属性。现在,对于每个项目,它会检查之前不在集合中的其他属性,并在将该记录添加到集合之前添加它们。

Edit3:更新了Add-Member命令以实现向后兼容性。直到现在我还没有意识到-NotePropertyName/Value是v3 +。

答案 2 :(得分:0)

我把一个PowerShell函数组合在一起。它假设您的XML结构很多,但它适用于您发布的内容。您只需将其传输到Out-File即可获取CSV。

Function ConvertFrom-XMLtoCSV {
    [CmdletBinding()]
    <#
    .Synopsis
       Convert a uniform XML file to CSV with element names as headers
    .DESCRIPTION
       Takes a uniformed XML tree and converts it to CSV based on the XPath given.

       For example, assume a structure like this:
       <root>
           <item>
               <element1>Content1</element1>
               <element2>Content2</element2>
           </item>
           <item>
               <element1>Content1</element1>
               <element2>Content2</element2>
           </item>
       <root>

    .PARAMETER Path
        The path to the XML File

    .PARAMETER XPath
        The XPath query to the items that should be converted

    .EXAMPLE
       ConvertFrom-XMLtoCSV -Path .\file.xml -XPath "//item" 
    #>
    Param (
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,Position=0)][String] $Path,
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,Position=1)][String] $XPath
    )
    Begin {
        if (Test-Path $Path) {
            [XML] $XML = Get-Content $Path -Raw
        } else {
            Throw [System.IO.FileNotFoundException] "XML file was not found at the given path"
        }
        $NodeCount = $XML.SelectNodes($XPath).Count
        $FileHeaders = [System.String]::Join(",",$($XML.SelectNodes("$XPath[1]/node()") | ForEach-Object { $_.ToString()}))
        $Content = @()
    }
    Process {
        $Content += $FileHeaders
        For ($i = 1; $i -le $NodeCount; $i++) { 
            $Content += [System.String]::Join(",",$($xml.SelectNodes("$XPath[$i]/node()") | ForEach-Object {$_."#text"}))
        }

        return $Content
    }
}