2015-06-01 23 views
2

命名空間CSV轉換XML我有這個XML文件:使用PowerShell的

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns3:BOX xmlns="urn:loc.gov:item" 
     xmlns:ns2="urn:loc.gov:box" 
     xmlns:ns3="http://www.example.com/inverter" 
     xmlns:ns4="urn:loc.gov:xyz"> 
    <ns3:Item> 
     <Description>ITEM1</Description> 
     <PackSizeNumeric>6</PackSizeNumeric> 
     <ns2:BuyersItemIdentification> 
      <ID>75847589</ID> 
     </ns2:BuyersItemIdentification> 
     <ns2:CommodityClassification> 
      <CommodityCode>856952</CommodityCode> 
     </ns2:CommodityClassification> 
     <ns2:AdditionalItemProperty> 
      <Name>Weight</Name> 
      <Value>0</Value> 
     </ns2:AdditionalItemProperty> 
     <ns2:AdditionalItemProperty> 
      <Name>Tare</Name> 
      <Value>0</Value> 
     </ns2:AdditionalItemProperty> 
     <ns2:ManufacturerParty> 
      <ns2:PartyIdentification> 
       <ID>847532</ID> 
      </ns2:PartyIdentification> 
     </ns2:ManufacturerParty> 
    </ns3:Item> 
    <ns3:Item> 
     <Description>ITEM2</Description> 
     <PackSizeNumeric>10</PackSizeNumeric> 
     <ns2:BuyersItemIdentification> 
      <ID>9568475</ID> 
     </ns2:BuyersItemIdentification> 
     <ns2:CommodityClassification> 
      <CommodityCode>348454</CommodityCode> 
     </ns2:CommodityClassification> 
     <ns2:AdditionalItemProperty> 
      <Name>Weight</Name> 
      <Value>0</Value> 
     </ns2:AdditionalItemProperty> 
     <ns2:AdditionalItemProperty> 
      <Name>Tare</Name> 
      <Value>0</Value> 
     </ns2:AdditionalItemProperty> 
     <ns2:ManufacturerParty> 
      <ns2:PartyIdentification> 
       <ID>7542125</ID> 
      </ns2:PartyIdentification> 
     </ns2:ManufacturerParty> 
    </ns3:Item> 
</ns3:BOX> 

我試圖將其轉換爲一個CSV文件。

我得到的內容:

[xml]$inputFile = Get-Content test.xml 

然後我導出爲CSV:

$inputfile.BOX.childnodes | Export-Csv "Stsadm-EnumSites.csv" -NoTypeInformation -Delimiter:";" -Encoding:UTF8 

我得到了DescriptionPackSizeNumeric領域而不是其他領域,其在:

"Description";"PackSizeNumeric";"BuyersItemIdentification";"CommodityClassification";"AdditionalItemProperty";"ManufacturerParty" 
"ITEM1";"6";"System.Xml.XmlElement";"System.Xml.XmlElement";"System.Object[]";"System.Xml.XmlElement" 
"ITEM2";"10";"System.Xml.XmlElement";"System.Xml.XmlElement";"System.Object[]";"System.Xml.XmlElement" 

哪個是獲取所包含字段的最佳方法其他名稱空間?

我想獲得這個

"Description";"PackSizeNumeric";"BuyersItemIdentification";"CommodityClassification";"Weight";"Tare";PartyIdentification 
"ITEM1";"6";"75847589";"856952";"0";"0";"847532" 
"ITEM2";"10";"9568475";"348454";"0";"0";"7542125" 
+0

顯示預期的效果。 – PetSerAl

+0

我改正了我的問題 – debharlock

+1

您的問題與XML名稱空間無關。 Export-Csv在將複雜對象轉換爲文本時遇到麻煩。所有複雜的元素在XML中都有名稱空間,這只是巧合。 – PetSerAl

回答

2

Select-ObjectSelect-Xml組合似乎工作得很好:

$ns = @{ 
    item="urn:loc.gov:item" 
    ns2="urn:loc.gov:box" 
    ns3="http://www.example.com/inverter" 
    ns4="urn:loc.gov:xyz" 
} 

([xml](Get-Content test.xml)).BOX.ChildNodes ` 
| Select-Object -Property ` 
    Description,` 
    PackSizeNumeric, ` 
    @{Name="BuyersItemIdentification_ID"; Expression={$_.BuyersItemIdentification.ID}}, ` 
    @{Name="CommodityClassification_CommodityCode"; Expression={$_.CommodityClassification.CommodityCode}}, ` 
    @{Name="Weight"; Expression={Select-Xml -Namespace $ns -Xml $_ -XPath "./ns2:AdditionalItemProperty[item:Name = 'Weight']/item:Value"}}, ` 
    @{Name="Tare"; Expression={Select-Xml -Namespace $ns -Xml $_ -XPath "./ns2:AdditionalItemProperty[item:Name = 'Tare']/item:Value"}}, ` 
    @{Name="ManufacturerParty_ID"; Expression={$_.ManufacturerParty.PartyIdentification.ID}} ` 
| Export-Csv "Stsadm-EnumSites.csv" -NoTypeInformation -Delimiter:";" -Encoding:UTF8 

結果(Stsadm-EnumSites.csv

 
"Description";"PackSizeNumeric";"BuyersItemIdentification_ID";"CommodityClassification_CommodityCode";"Weight";"Tare";"ManufacturerParty_ID" 
"ITEM1";"6";"75847589";"856952";"0";"0";"847532" 
"ITEM2";"10";"9568475";"348454";"0";"0";"7542125" 
+0

酷豆!比我試圖通過子節點進行迭代要好得多。 –

+0

Thanks @Vincent :)它仍然感覺有點麻煩,但至少它在列命名和節點選擇方面非常明確。 – Tomalak

+0

我完成了我的解決方案,有任何意見?仍然在這裏學習:p –

1

託默勒格的回答是簡潔,似乎對眼前的問題,最好的解決辦法。

我試圖做一些東西通用,但結果甚至沒有要求的格式(附加屬性列表很難以通用的方式轉換,字段名稱是笨重的)。無論如何,下面的解決方案沿着XML樹平坦化數據。它不受元素名稱的限制(除了最初的選擇)

完成我的通用答案後,我現在想知道是不是應該寫一個XSLT轉換&。

#[xml]$xml = Get-Content test.xml 
#xml to process 
$xml = [xml]@" 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns3:BOX xmlns="urn:loc.gov:item" 
     xmlns:ns2="urn:loc.gov:box" 
     xmlns:ns3="http://www.example.com/inverter" 
     xmlns:ns4="urn:loc.gov:xyz"> 
    <ns3:Item> 
     <Description>ITEM1</Description> 
     <PackSizeNumeric>6</PackSizeNumeric> 
     <ns2:BuyersItemIdentification> 
      <ID>75847589</ID> 
     </ns2:BuyersItemIdentification> 
     <ns2:CommodityClassification> 
      <CommodityCode>856952</CommodityCode> 
     </ns2:CommodityClassification> 
     <ns2:AdditionalItemProperty> 
      <Name>Weight</Name> 
      <Value>0</Value> 
     </ns2:AdditionalItemProperty> 
     <ns2:AdditionalItemProperty> 
      <Name>Tare</Name> 
      <Value>0</Value> 
     </ns2:AdditionalItemProperty> 
     <ns2:ManufacturerParty> 
      <ns2:PartyIdentification> 
       <ID>847532</ID> 
      </ns2:PartyIdentification> 
     </ns2:ManufacturerParty> 
    </ns3:Item> 
    <ns3:Item> 
     <Description>ITEM2</Description> 
     <PackSizeNumeric>10</PackSizeNumeric> 
     <ns2:BuyersItemIdentification> 
      <ID>9568475</ID> 
     </ns2:BuyersItemIdentification> 
     <ns2:CommodityClassification> 
      <CommodityCode>348454</CommodityCode> 
     </ns2:CommodityClassification> 
     <ns2:AdditionalItemProperty> 
      <Name>Weight</Name> 
      <Value>0</Value> 
     </ns2:AdditionalItemProperty> 
     <ns2:AdditionalItemProperty> 
      <Name>Tare</Name> 
      <Value>0</Value> 
     </ns2:AdditionalItemProperty> 
     <ns2:ManufacturerParty> 
      <ns2:PartyIdentification> 
       <ID>7542125</ID> 
      </ns2:PartyIdentification> 
     </ns2:ManufacturerParty> 
    </ns3:Item> 
</ns3:BOX> 
"@ 

$nsm = [Xml.XmlNamespaceManager]$xml.NameTable 

$nsm.AddNamespace("ns1","urn:loc.gov:item") 
$nsm.AddNamespace("ns2","urn:loc.gov:box") 
$nsm.AddNamespace("ns3","http://www.example.com/inverter") 
$nsm.AddNamespace("ns4","urn:loc.gov:xyz") 

#function to recursively flatten xml subtree into a hashtable (passed in) 
function flatten-xml { 
    param (
    $Parent, 
    $Element, 
    $Fieldname, 
    $HashTable 
) 

    if ($parent -eq "") { 
    $label = $fieldname 
    } else { 
    $label = $parent + "_" + $fieldname 
    } 

    #write-host "$label is $($element.GetType())" 

    if ($element.GetType() -eq [System.Xml.XmlElement]) { 
    #get property fields 

    $element | Get-Member | ? { $_.MemberType -eq "Property" } | % { 
     #write-host "moving from $label to $($_.Name)" 
     flatten-xml -Parent $label -Element $element.($_.Name) -FieldName $_.Name -HashTable $HashTable 
    } 
    }elseif($element.GetType() -eq [System.Object[]]) { 
    #write-host "$label is an array" 
    $i = 0 
    $element | % { flatten-xml -Parent $label -Element $_ -FieldName "item$i" -HashTable $HashTable; $i++ } 
    }else { 
    $HashTable[$label] = $element 
    } 
} 

#convert the nodecollection returned by xpath query into hashtables and write them out to CSV 
$xml.SelectNodes("//ns3:BOX/ns3:Item",$nsm) | % { 
    $element = $_ 
    $ht = @{} 
    $element | Get-Member | ? { $_.MemberType -eq "Property" } | % { 
     flatten-xml -Parent "" -Element $element.($_.Name) -FieldName $_.Name -HashTable $ht 
    } 

    [PSCustomObject]$ht 
} | Export-Csv "test2.csv" -NoTypeInformation -Delimiter:";" -Encoding:UTF8 

結果:

> gc .\test2.csv 

"AdditionalItemProperty_item0_Name";"AdditionalItemProperty_item0_Value";"AdditionalItemProperty_item1_Name";"AdditionalItemProperty_item1_Value";"BuyersItemIdentification_ID";"CommodityClassification_CommodityCode";"Description";"ManufacturerParty_PartyIdentification_ID";"PackSizeNumeric" 
"Weight"       ;"0"         ;"Tare"        ;"0"         ;"75847589"     ;"856952"        ;"ITEM1"  ;"847532"         ;"6" 
"Weight"       ;"0"         ;"Tare"        ;"0"         ;"9568475"     ;"348454"        ;"ITEM2"  ;"7542125"         ;"10" 

參考文獻:

+0

您的解決方案更復雜,但它對我的XML研究很有趣。 有兩個錯誤:-) 1)字段的順序。 Description,PackSizeNumeric,ecc ecc 2)重量和皮重是列的名稱 :-) – debharlock

+0

我不能在我的評論中添加行括號....對不起 – debharlock

+0

沒關係。關於你的評論:1.秩序 - 似乎散列表改變了鍵(元素名稱)的順序,我還沒有嘗試找到一種方法來尊重秩序和2.重量和皮重是一個數組中的2個元素,他們不是列自己在你給的XML結構中。這是我在我的描述中強調的內容,我覺得你不能以通用的方式將這個值列表轉換爲列。 –