2013-02-20 45 views
0

我是相當新的Powershell,我有我相當奇怪的XML,我的主要目標是將XML轉換爲CSV,它將進一步用於同步到數據庫。 我已經使用Powershell代碼將xml提取到哈希中。 現在我有問題轉換成CSV。 Export-csv只寫入散列中的最後一個條目。不知道爲什麼這個,我檢查了幾個其他論壇,他們說Export-csv中的-append功能只與powershell 3.0,我使用1.0 ..Powershell XML Export-csv不附加散列

你能幫我解決這個問題嗎?

XML:

<catalog> 
<segment> 
<segmentname>Batch</segmentname> 
<hosts> 
<host> 
<hostname>cglist17</hostname> 
</host> 
<host> 
<hostname>cglist18</hostname> 
</host> 
<host> 
<hostname>cglist19</hostname> 
</host> 
<host> 
<hostname>cglist20</hostname> 
</host> 
</hosts> 
</segment> 
<segment> 
<segmentname>Custom S2</segmentname> 
<hosts> 
<host> 
<hostname>cglist21</hostname> 
</host> 
<host> 
<hostname>cglist22</hostname> 
</host> 
</hosts> 
</segment> 
<segment> 
<segmentname>eCommerce</segmentname> 
<hosts> 
<host> 
<hostname>cglist09</hostname> 
</host> 
<host> 
<hostname>cglist10</hostname> 
</host> 
</hosts> 
</segment> 
</catalog> 

PowerShell代碼:

[xml]$xd=gc "C:\Users\sxa8869\Desktop\Webserv\segmentcat.xml" 
$nodelist = $xd.selectnodes("/catalog/segment") 

$MasterArray = @() 
$MasterArray = "" | Select segmentname,hosts 

$file="C:\Users\sxa8869\Desktop\Webserv\sha.csv" 

foreach ($node in $nodelist) { 

    $hostsNode = $node.selectSingleNode("hosts") 
    $segmentname = $node.selectSingleNode("segmentname") 
    $MasterArray.segmentname=$segmentname.get_InnerXml() 
    foreach ($hostitem in $hostsNode) { 
    $hostnamenodes = $hostitem.selectnodes("host") 
    foreach ($hostname in $hostnamenodes) { 
     $MasterArray.hosts=$hostname.selectSingleNode("hostname").get_InnerXml() 

#- Displays the hash in table format, want this format in csv 
     $MasterArray   

# - displaying only the last element 
     $MasterArray | export-csv "file.csv" -notype  

# - this works, but i want to use export-csv to get it in this format 
'"'+$MasterArray.segmentname+'"'+","+'"'+$MasterArray.hosts+'"'  

    }  
    } 
} 


Required output :- 
----------------- 
"segmentname","hosts" 
"Batch","cglist17" 
"Batch","cglist18" 
"Batch","cglist19" 
"Batch","cglist20" 
"Custom S2","cglist21" 
"Custom S2","cglist22" 
"eCommerce","cglist09" 
eCommerce,"cglist10" 

回答

0

您在這裏有多個問題。首先,您創建一個數組MasterArray,但您將其設置爲等於您使用Select創建的自定義對象。現在MasterArray不再是一個數組,而是一個pscustomobject。第二,將值設置爲單個對象屬性,每次都會覆蓋最後一個條目。一個數組需要包含多個對象。我重寫了它。我沒有使用管道等提高,但簡單地固定你的錯誤,;-)腳本:

[xml]$xd = gc "C:\Users\sxa8869\Desktop\Webserv\segmentcat.xml" 
$nodelist = $xd.selectnodes("/catalog/segment") 

$MasterArray = @() 

$file="C:\Users\sxa8869\Desktop\Webserv\sha.csv" 

foreach ($node in $nodelist) { 

    $hostsNode = $node.SelectSingleNode("hosts") 
    $segmentname = $node.SelectSingleNode("segmentname") 
    #Store static value for all objects in $node 
    $segname = $segmentname.InnerText 

    foreach ($hostitem in $hostsNode) { 
     $hostnamenodes = $hostitem.SelectNodes("host") 
     foreach ($hostname in $hostnamenodes) { 
      #Add hostrecord to array 
      $MasterArray += New-Object psobject -Property @{ 
      "Segment Name" = $segname 
      "Host Name" = $hostname.InnerText 
      } 
     } 
    } 
} 

#Output to console 
$MasterArray   

#Save to file (path in $file variable = "...\sha.csv"). 
#Using Select-Object to specify order of columns 
$MasterArray | Select-Object "Segment Name", "Host Name" | Export-Csv $file -NoTypeInformation 

產出「sha.csv」:

"Segment Name","Host Name" 
"Batch","cglist17" 
"Batch","cglist18" 
"Batch","cglist19" 
"Batch","cglist20" 
"Custom S2","cglist21" 
"Custom S2","cglist22" 
"eCommerce","cglist09" 
"eCommerce","cglist10" 
+0

'$ MasterArray + =新物體psobject,物業@ {分段名= $ segname的主機= $ hostname.InnerText}'@Graimer:這是偉大的!工作完美..但我想了解更多。你會不會是我的一些基本問題?糾正我,如果即時通訊錯誤.. – 2013-02-25 14:53:36

+0

我的問題是在我已經提到的線..首先我明白+ =添加元素到數組中,這是唯一的方式來添加他們?? ..當我打印我的$ MasterArray,爲什麼它首先打印主機列,然後是segementname ..很抱歉,如果這些是基本問題,我希望從這個基礎知識。 – 2013-02-25 14:59:50

+0

'+ ='是最好的方法。你有一個叫做Add()的方法,但它總是會失敗。數組是固定大小,不能添加元素。要添加元素,需要創建一個包含舊數組值和新值(這在內存中完成)的新數組,然後將其保存爲變量(例如覆蓋舊數組)。這就是'+ ='所做的。數組沒有固定的列順序,所以輸出是「隨機的」。使用'$ array |格式 - 表格(或格式 - 列表) - 物業Column1,Column2等'設置您的訂單。如果您有更多問題,請在此處搜索。以前回答最基本的問題。 – 2013-02-25 15:23:06

1

我覺得你很過分使事情複雜化。試試這個:

$myXML = [xml](Get-Content "C:\Users\sxa8869\Desktop\Webserv\segmentcat.xml") 
$file="C:\Users\sxa8869\Desktop\Webserv\sha.csv" 

$myArray = @() 
foreach ($s in $myXML.catalog.segment) 
{ 
    foreach ($h in $s.hosts.host) 
    { 
     $myArray += New-Object -TypeName PSObject -Property @{"Segment Name" = $s.segmentname; "Host Name" = $h.hostname} 
    } 
} 

$myArray | Export-Csv $file -NoTypeInformation 
+0

感謝噸,工程很好..你已經最小化了代碼行,使它更高效..但只是想知道是解析XML的最佳方式,我看到了很多方法在stackoverflow ..'$ myArray' - 這會叫什麼?數組,hasharray,多維數組? – 2013-02-25 15:13:39

+0

「最好」的方式是你喜歡的方式。 xpath和「財產方式」(如上面的)都做同樣的事情。在這種情況下,'$ myArray = @()',那麼它被稱爲「數組」 – 2013-02-25 15:26:19

+0

正如Graimer暗示的那樣,有多種「最好」的做事方式。你想要最可讀,最好的表演,還是什麼?我傾向於傾向於可讀性,除非我發現了一個特殊的瓶頸。但是,可讀性非常主觀,取決於您已經熟悉的內容。 – KevinD 2013-02-25 19:57:22