【问题标题】:Powershell - convert XML to CSVPowershell - 将 XML 转换为 CSV
【发布时间】:2017-09-09 16:13:29
【问题描述】:

我能够使用以下代码将 XML 转换为 CSV:

    #read from file
[xml]$inputFile = Get-Content "c:\pstest\test.xml"
#export xml as csv
$inputFile.Transaction.ChildNodes | Export-Csv "c:\pstest\test.csv" -NoTypeInformation -Delimiter:";" -Encoding:UTF8

如果文件只包含一个根节点和一种子节点,例如:

<?xml version="1.0" encoding="UTF-8"?>
<Transaction>
    <TXNDETAIL>
        <RecordID>02</RecordID>
        <SequenceNumber>1</SequenceNumber>
        <TransactionType>01</TransactionType>
        <ActionCode>01</ActionCode>
        <TransactionID>17500515552017001</TransactionID>
        <SellerCode>2200919TRY</SellerCode>
        <BuyerCode>KOCZER</BuyerCode>
        <TransactionReference> </TransactionReference>
        <TransactionDescription1> </TransactionDescription1>
        <TransactionDescription2> </TransactionDescription2>
        <DocumentType>01</DocumentType>
        <DocumentNumber>XXXXXXXXXXX</DocumentNumber>
        <DocumentDate>20170301</DocumentDate>
        <DocumentAmount>10000</DocumentAmount>
        <CurrencyCode>949</CurrencyCode>
        <TransactionAmount>10000</TransactionAmount>
        <TransactionDueDate>20170505</TransactionDueDate>
        <AdditionalInformation1> </AdditionalInformation1>
        <AdditionalInformation2> </AdditionalInformation2>
        <HashCode>XXXXXXXX</HashCode>
    </TXNDETAIL>
    <TXNDETAIL>
        <RecordID>02</RecordID>
        <SequenceNumber>2</SequenceNumber>
        <TransactionType>01</TransactionType>
        <ActionCode>01</ActionCode>
        <TransactionID>17500515622017001</TransactionID>
        <SellerCode>2200919TRY</SellerCode>
        <BuyerCode>KOCZER</BuyerCode>
        <TransactionReference> </TransactionReference>
        <TransactionDescription1> </TransactionDescription1>
        <TransactionDescription2> </TransactionDescription2>
        <DocumentType>01</DocumentType>
        <DocumentNumber>XXXXXXXXXXX</DocumentNumber>
        <DocumentDate>20170301</DocumentDate>
        <DocumentAmount>10000</DocumentAmount>
        <CurrencyCode>949</CurrencyCode>
        <TransactionAmount>10000</TransactionAmount>
        <TransactionDueDate>20170505</TransactionDueDate>
        <AdditionalInformation1> </AdditionalInformation1>
        <AdditionalInformation2> </AdditionalInformation2>
        <HashCode>XXXXXXXX</HashCode>
    </TXNDETAIL>
    <TXNDETAIL>
        <RecordID>02</RecordID>
        <SequenceNumber>3</SequenceNumber>
        <TransactionType>01</TransactionType>
        <ActionCode>01</ActionCode>
        <TransactionID>17500515972017001</TransactionID>
        <SellerCode>2200919TRY</SellerCode>
        <BuyerCode>KOCZER</BuyerCode>
        <TransactionReference> </TransactionReference>
        <TransactionDescription1> </TransactionDescription1>
        <TransactionDescription2> </TransactionDescription2>
        <DocumentType>01</DocumentType>
        <DocumentNumber>XXXXXXXXXXX</DocumentNumber>
        <DocumentDate>20170301</DocumentDate>
        <DocumentAmount>10000</DocumentAmount>
        <CurrencyCode>949</CurrencyCode>
        <TransactionAmount>10000</TransactionAmount>
        <TransactionDueDate>20170505</TransactionDueDate>
        <AdditionalInformation1> </AdditionalInformation1>
        <AdditionalInformation2> </AdditionalInformation2>
        <HashCode>XXXXXXXX</HashCode>
    </TXNDETAIL>
</Transaction>

输出如下:

    "RecordID";"SequenceNumber";"TransactionType";"ActionCode";"TransactionID";"SellerCode";"BuyerCode";"TransactionReference";"TransactionDescription1";"TransactionDescription2";"DocumentType";"DocumentNumber";"DocumentDate";"DocumentAmount";"CurrencyCode";"TransactionAmount";"TransactionDueDate";"AdditionalInformation1";"AdditionalInformation2";"HashCode"
"02";"1";"01";"01";"17500515552017001";"2200919TRY";"KOCZER";"";"";"";"01";"XXXXXXXXXXX";"20170301";"10000";"949";"10000";"20170505";"";"";"XXXXXXXX"
"02";"2";"01";"01";"17500515622017001";"2200919TRY";"KOCZER";"";"";"";"01";"XXXXXXXXXXX";"20170301";"10000";"949";"10000";"20170505";"";"";"XXXXXXXX"
"02";"3";"01";"01";"17500515972017001";"2200919TRY";"KOCZER";"";"";"";"01";"XXXXXXXXXXX";"20170301";"10000";"949";"10000";"20170505";"";"";"XXXXXXXX"

这很棒。

然而现实中的输入文件有一个“标题行”信息,TXNHEAD标签

    <?xml version="1.0" encoding="UTF-8"?>
<Transaction>
    <TXNHEAD>
        <RecordID>01</RecordID>
        <FileName>001</FileName>
        <IntermediaryCode>19000033</IntermediaryCode>
        <ActualizationDate>20170314</ActualizationDate>
        <SequenceNumber>001</SequenceNumber>
        <NumberofRecords>3</NumberofRecords>
        <AmountofRecords>30000</AmountofRecords>
    </TXNHEAD>
    <TXNDETAIL>
        <RecordID>02</RecordID>
        <SequenceNumber>1</SequenceNumber>
        <TransactionType>01</TransactionType>
        <ActionCode>01</ActionCode>
        <TransactionID>17500515552017001</TransactionID>
        <SellerCode>2200919TRY</SellerCode>
        <BuyerCode>KOCZER</BuyerCode>
        <TransactionReference> </TransactionReference>
        <TransactionDescription1> </TransactionDescription1>
        <TransactionDescription2> </TransactionDescription2>
        <DocumentType>01</DocumentType>
        <DocumentNumber>XXXXXXXXXXX</DocumentNumber>
        <DocumentDate>20170301</DocumentDate>
        <DocumentAmount>10000</DocumentAmount>
        <CurrencyCode>949</CurrencyCode>
        <TransactionAmount>10000</TransactionAmount>
        <TransactionDueDate>20170505</TransactionDueDate>
        <AdditionalInformation1> </AdditionalInformation1>
        <AdditionalInformation2> </AdditionalInformation2>
        <HashCode>XXXXXXXX</HashCode>
    </TXNDETAIL>
    <TXNDETAIL>
        <RecordID>02</RecordID>
        <SequenceNumber>2</SequenceNumber>
        <TransactionType>01</TransactionType>
        <ActionCode>01</ActionCode>
        <TransactionID>17500515622017001</TransactionID>
        <SellerCode>2200919TRY</SellerCode>
        <BuyerCode>KOCZER</BuyerCode>
        <TransactionReference> </TransactionReference>
        <TransactionDescription1> </TransactionDescription1>
        <TransactionDescription2> </TransactionDescription2>
        <DocumentType>01</DocumentType>
        <DocumentNumber>XXXXXXXXXXX</DocumentNumber>
        <DocumentDate>20170301</DocumentDate>
        <DocumentAmount>10000</DocumentAmount>
        <CurrencyCode>949</CurrencyCode>
        <TransactionAmount>10000</TransactionAmount>
        <TransactionDueDate>20170505</TransactionDueDate>
        <AdditionalInformation1> </AdditionalInformation1>
        <AdditionalInformation2> </AdditionalInformation2>
        <HashCode>XXXXXXXX</HashCode>
    </TXNDETAIL>
    <TXNDETAIL>
        <RecordID>02</RecordID>
        <SequenceNumber>3</SequenceNumber>
        <TransactionType>01</TransactionType>
        <ActionCode>01</ActionCode>
        <TransactionID>17500515972017001</TransactionID>
        <SellerCode>2200919TRY</SellerCode>
        <BuyerCode>KOCZER</BuyerCode>
        <TransactionReference> </TransactionReference>
        <TransactionDescription1> </TransactionDescription1>
        <TransactionDescription2> </TransactionDescription2>
        <DocumentType>01</DocumentType>
        <DocumentNumber>XXXXXXXXXXX</DocumentNumber>
        <DocumentDate>20170301</DocumentDate>
        <DocumentAmount>10000</DocumentAmount>
        <CurrencyCode>949</CurrencyCode>
        <TransactionAmount>10000</TransactionAmount>
        <TransactionDueDate>20170505</TransactionDueDate>
        <AdditionalInformation1> </AdditionalInformation1>
        <AdditionalInformation2> </AdditionalInformation2>
        <HashCode>XXXXXXXX</HashCode>
    </TXNDETAIL>
</Transaction>

当应用相同的代码时,我得到:

    "RecordID";"FileName";"IntermediaryCode";"ActualizationDate";"SequenceNumber";"NumberofRecords";"AmountofRecords"
"01";"001";"19000033";"20170314";"001";"3";"30000"
"02";;;;"1";;
"02";;;;"2";;
"02";;;;"3";;

当我尝试使用此代码来检索头部时:

#read from file
[xml]$inputFile = Get-Content "c:\pstest\test.xml"
#export xml as csv
$inputFile.Transaction.TXNHEAD.ChildNodes | Export-Csv "c:\pstest\test.csv" -NoTypeInformation -Delimiter:";" -Encoding:UTF8

我明白了:

"#text"
"01"
"001"
"19000033"
"20170314"
"001"
"3"
"30000"

我想要实现的是这个输出:

"RecordID";"FileName";"IntermediaryCode";"ActualizationDate";"SequenceNumber";"NumberofRecords";"AmountofRecords"
"01";"001";"19000033";"20170314";"001";"3";"30000"
"RecordID";"SequenceNumber";"TransactionType";"ActionCode";"TransactionID";"SellerCode";"BuyerCode";"TransactionReference";"TransactionDescription1";"TransactionDescription2";"DocumentType";"DocumentNumber";"DocumentDate";"DocumentAmount";"CurrencyCode";"TransactionAmount";"TransactionDueDate";"AdditionalInformation1";"AdditionalInformation2";"HashCode"
"02";"1";"01";"01";"17500515552017001";"2200919TRY";"KOCZER";"";"";"";"01";"XXXXXXXXXXX";"20170301";"10000";"949";"10000";"20170505";"";"";"XXXXXXXX"
"02";"2";"01";"01";"17500515622017001";"2200919TRY";"KOCZER";"";"";"";"01";"XXXXXXXXXXX";"20170301";"10000";"949";"10000";"20170505";"";"";"XXXXXXXX"
"02";"3";"01";"01";"17500515972017001";"2200919TRY";"KOCZER";"";"";"";"01";"XXXXXXXXXXX";"20170301";"10000";"949";"10000";"20170505";"";"";"XXXXXXXX"

我做错了什么?

【问题讨论】:

    标签: xml powershell csv


    【解决方案1】:

    管道中的第一个对象(或Select-Object 等)定义了输出的标头,无论它是文件输出还是控制台输出。

    您可以做的是在两轮中将它们转换为 csv 并将其添加到同一个文件中。例如:

    $inputFile.Transaction.TXNHEAD | ConvertTo-Csv -NoTypeInformation -Delimiter ";" | Set-Content -Path "c:\pstest\test.csv" -Encoding UTF8
    $inputFile.Transaction.TXNDETAIL | ConvertTo-Csv -NoTypeInformation -Delimiter ";" | Add-Content -Path "c:\pstest\test.csv" -Encoding UTF8
    

    你也可以这样组合它们:

    $inputFile.Transaction.TXNHEAD, $x.Transaction.TXNDETAIL |
    ForEach-Object { $_ | ConvertTo-Csv -NoTypeInformation -Delimiter ";" } |
    Set-Content -Path "c:\pstest\test.csv" -Encoding UTF8
    

    【讨论】:

    • 因为他希望类型信息出现在 CSV 中,最好不要包含 NoTypeInformation 标志。
    • 他没有。再读一遍
    • 嗯。他说:“我想要以下输出:”并且输出包含类型信息行,从RecordID 开始。请检查问题中的最后一个代码块。
    • 那么请添加您的答案,因为据我所知,您正在编造报价和细节。他想要他的标头(TXNHEAD-node)中的值。 Export-CSV 的 TypeInformation 完全是另外一回事。我的答案产生了所需的输出
    【解决方案2】:

    这是我的代码:

    # ============================================================================= 
    #  
    # NAME:xml2csv.ps1
    #  
    # AUTHOR: 
    # THANKS TO: Rick Sheeley (original snippet on STack Overflow) 
    # DATE  : 
    #  
    # COMMENT:  
    # Send large XML with multiple children and Attributes to CSv for analysis
    #
    # Note: For versions 3.0 or newer only
    # ============================================================================= 
    
    function Get-Attributes([Object]$pnode)
    {
    
        if($pnode.HasAttributes) {
    
            foreach($attr in $pnode.Attributes) {
    
                $xattString+= $attr.Name + ":" + $attr."#text" + ","
    
            }
    
        }
    
        else {
    
                $xattString = $pnode.nNode + ": No Attributes,"
    
        }
    
        return $xattString
    }
    
    function Get-XmlNode([ xml ]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
    {
        # If a Namespace URI was not given, use the Xml document's default namespace.
        if ([string]::IsNullOrEmpty($NamespaceURI)) { $NamespaceURI = $XmlDocument.DocumentElement.NamespaceURI }   
    
        # In order for SelectSingleNode() to actually work, we need to use the fully qualified node path along with an Xml Namespace Manager, so set them up.
        $xmlNsManager = New-Object System.Xml.XmlNamespaceManager($XmlDocument.NameTable)
        $xmlNsManager.AddNamespace("ns", $NamespaceURI)
        $fullyQualifiedNodePath = "/ns:$($NodePath.Replace($($NodeSeparatorCharacter), '/ns:'))"
    
        # Try and get the node, then return it. Returns $null if the node was not found.
        $node = $XmlDocument.SelectSingleNode($fullyQualifiedNodePath, $xmlNsManager)
        return $node
    }
    
    cls
    $fin = "<Filepath>\<myFile>.xml"
    $fout = "<Filepath>\<myFile>.csv"
    
    Remove-Item $fout -ErrorAction SilentlyContinue
    
    [xml]$xmlContent = get-content $fin
    $row=0
    $COMMA=","
    $pNode = "ROOT"
    
    # Replace all "MyTopNode" with your top node...
    
    $nNode = "MyTopNode"
    
    $xmlArray  = @(
        [pscustomobject]@{Row= $row;Parent=$pNode;Node=$nNode;Attribute='';ItemType='Root';Value=''})
    
    $xmlArray[$row].Row = $row
    $xmlArray[$row].Parent = $pNode
    $xmlArray[$row].Node = $nNode
    $xmlArray[$row].Attribute = ""
    $xmlArray[$row].ItemType = "Root"
    $xmlArray[$row].Value = $attr."#text"
    $row++
    
    if($xmlContent.MyTopNode.HasAttributes) {
    
        foreach($attr in $xmlContent.MyTopNode.Attributes) {
    
            $xmlArray += @(
                [pscustomobject]@{Row= $row;Parent=$pNode;Node=$nNode;Attribute='';ItemType='Root';Value=''})
    
            $xmlArray[$row].Row = $row
            $xmlArray[$row].Parent = $pNode
            $xmlArray[$row].Node = $nNode
            $xmlArray[$row].Attribute = $attr.LocalName
            $xmlArray[$row].ItemType = "Attribute"
            $xmlArray[$row].Value = $attr."#text"
            $row++
    
        }
    
    }
    
    # Begin TRY
    
    try {
    
        foreach($node in $xmlContent.MyTopNode.ChildNodes) {
    
            $pNode = "MyTopNode"
    
            $nNode = $node.LocalName
    
            $xmlArray += @(
                [pscustomobject]@{Row= $row;Parent=$pNode;Node=$nNode;Attribute='';ItemType='Root';Value=''})
    
            $xmlArray[$row].Row = $row
            $xmlArray[$row].Parent = $pNode
            $xmlArray[$row].Node = $nNode
            $xmlArray[$row].Attribute = ""
            $xmlArray[$row].ItemType = "Root"
            $xmlArray[$row].Value = $attr."#text"
            $row++
    
            if($nNode.HasAttributes) {
    
                foreach($attr in $node.Attributes) {
    
                    $xmlArray += @(
                        [pscustomobject]@{Row= $row;Parent=$pNode;Node=$nNode;Attribute='';ItemType='Root';Value=''})
    
                    $xmlArray[$row].Row = $row
                    $xmlArray[$row].Parent = $pNode
                    $xmlArray[$row].Node = $nNode
                    $xmlArray[$row].Attribute = $attr.LocalName
                    $xmlArray[$row].ItemType = "Attribute"
                    $xmlArray[$row].Value = $attr."#text"
                    $row++
    
                }
    
            }
    
            foreach($sNode in $node.ChildNodes) {
    
                $pNode = $nNode
                $snNode = $sNode.LocalName
    
                $xmlArray += @(
                    [pscustomobject]@{Row= $row;Parent=$pNode;Node=$nNode;Attribute='';ItemType='Root';Value=''})
    
                $xmlArray[$row].Row = $row
                $xmlArray[$row].Parent = $pNode
                $xmlArray[$row].Node = $snNode
                $xmlArray[$row].Attribute = ""
                $xmlArray[$row].ItemType = "Root"
                $xmlArray[$row].Value = $attr."#text"
                $row++
    
                if($sNode.HasAttributes) {
    
                    foreach($attr in $sNode.Attributes) {
    
                        $xmlArray += @(
                            [pscustomobject]@{Row= $row;Parent=$pNode;Node=$nNode;Attribute='';ItemType='Root';Value=''})
    
                        $xmlArray[$row].Row = $row
                        $xmlArray[$row].Parent = $pNode
                        $xmlArray[$row].Node = $snNode
                        $xmlArray[$row].Attribute = $attr.LocalName
                        $xmlArray[$row].ItemType = "Attribute"
                        $xmlArray[$row].Value = $attr."#text"
                        $row++
    
                    }
    
                }
            }
        }
    
        $xmlArray | SELECT Row,Parent,Node,Attribute,ItemType,Value | Export-CSV $fout -NoTypeInformation
    }
    
    # End TRY
    
    # Begin Catch
    
    Catch [System.Runtime.InteropServices.COMException]
    {
        $ErrException = Format-ErrMsg -errmsg $_.Exception
        $ErrorMessage = $_.Exception.Message
        $ErrorID = $_.FullyQualifiedErrorId
        $line = $_.InvocationInfo.ScriptLineNumber
    
        Write-Host                           "  "
        Write-Host                           "  "
        Write-Host -ForegroundColor DarkMagenta  ""
        Write-Host -ForegroundColor Magenta      "==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!=="
        Write-Host -ForegroundColor DarkMagenta  ""
        Write-Host -ForegroundColor DarkCyan     "Details:"  
        Write-Host -ForegroundColor White        "---------------------------------------------------------------------------------------------------------------------------------------------------- "
        Write-Host -ForegroundColor Cyan         "`t  Module:        $modname"
        Write-Host -ForegroundColor Cyan         "`t Section:        $sFunc"
        Write-Host -ForegroundColor Cyan         "`t On Line:        $line"
        Write-Host -ForegroundColor Cyan         "`t File:           $fSearchFile | Search will be skipped!!"
        Write-Host -ForegroundColor White        "---------------------------------------------------------------------------------------------------------------------------------------------------- "
        Write-Host -ForegroundColor DarkCyan      "Exception Message:"  
        Write-Host -ForegroundColor White       "---------------------------------------------------------------------------------------------------------------------------------------------------- "
        Write-Host -ForegroundColor Yellow       "`t ShortMessage:   $ErrorMessage"       
        Write-Host -ForegroundColor Yellow       "`t ErrorID:        $ErrorID"
        Write-Host -ForegroundColor White        "---------------------------------------------------------------------------------------------------------------------------------------------------- "
        Write-Host -ForegroundColor Magenta      "$ErrException"  
        Write-Host -ForegroundColor White        "---------------------------------------------------------------------------------------------------------------------------------------------------- "
        Write-Host -ForegroundColor DarkMagenta  "========================================================================================================================================== "
        Write-Host -ForegroundColor Yellow       "This File will be added to the Skip list. Please restart script $sScriptName ...." 
        Write-Host -ForegroundColor DarkMagenta  "========================================================================================================================================== "
        Write-Host                           "  "
        Write-Host                           "  "
    }
    
    Catch
    {
        $ErrException = Format-ErrMsg -errmsg $_.Exception
        $ErrorMessage = $_.Exception.Message
        $ErrorID = $_.FullyQualifiedErrorId
        $line = $_.InvocationInfo.ScriptLineNumber
    
        Write-Host                           "  "
        Write-Host                           "  "
        Write-Host -ForegroundColor DarkRed  "================================================================================================================================================="
        Write-Host -ForegroundColor Red      "==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!==!!Error!!=="
        Write-Host -ForegroundColor DarkRed  "================================================================================================================================================="
        Write-Host -ForegroundColor DarkCyan "Details:"  
        Write-Host -ForegroundColor White    "---------------------------------------------------------------------------------------------------------------------------------------------------- "
        Write-Host -ForegroundColor Cyan     "`t  Module:        $modname"
        Write-Host -ForegroundColor Cyan     "`t Section:        $sFunc"
        Write-Host -ForegroundColor Cyan     "`t On Line:        $line"
        Write-Host -ForegroundColor Cyan     "`t File:           $fSearchFile"
        Write-Host -ForegroundColor White    "---------------------------------------------------------------------------------------------------------------------------------------------------- "
        Write-Host -ForegroundColor DarkCyan "Exception Message:"  
        Write-Host -ForegroundColor White    "---------------------------------------------------------------------------------------------------------------------------------------------------- "
        Write-Host -ForegroundColor Yellow      "`t ShortMessage:   $ErrorMessage"       
        Write-Host -ForegroundColor Magenta  "`t ErrorID:        $ErrorID"
        Write-Host -ForegroundColor White    "---------------------------------------------------------------------------------------------------------------------------------------------------- "
        Write-Host -ForegroundColor Red      "$ErrException"  
        Write-Host -ForegroundColor White    "---------------------------------------------------------------------------------------------------------------------------------------------------- "
    
    # Show etended error info if in debug mode.
    
        if ($extDebug -eq $true) {
    
            Write-Host -ForegroundColor White    "---------------------------------------------------------------------------------------------------------------------------------------------------- "
            Write-Host -ForegroundColor Red      "Extended Debugging info"  
    
            Write-Host -ForegroundColor White    "---------------------------------------------------------------------------------------------------------------------------------------------------- "
            $error[0].Exception | Format-List * -Force
            Write-Host -ForegroundColor White    "---------------------------------------------------------------------------------------------------------------------------------------------------- "
    
        }
    
        Write-Host -ForegroundColor DarkRed  "==================================================================================================================================================== "
        Write-Host -ForegroundColor DarkRed  "==================================================================================================================================================== "
        Write-Host                           "  "
        Write-Host                           "  "
    
        Break
    
    # End Catch
    
    }
    
    # Begin Finally
    
    Finally
    {
        "finis."
        Exit 0
    
    # End Finally
    
    }
    

    【讨论】:

      猜你喜欢
      • 2020-06-10
      • 1970-01-01
      • 1970-01-01
      • 2019-12-11
      • 2022-01-23
      • 2021-02-17
      • 1970-01-01
      • 1970-01-01
      • 2013-06-20
      相关资源
      最近更新 更多