Powershell - 将XML转换为CSV

问题描述 投票:5回答:2

我可以使用以下代码将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
2个回答
2
投票

管道中的第一个对象(或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

1
投票

这是我的代码:

# ============================================================================= 
#  
# 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

}
© www.soinside.com 2019 - 2024. All rights reserved.