2013-02-20 2 views
0

Я довольно новичок в Powershell, у меня есть довольно странный xml по мне. Моя главная цель - преобразовать XML в CSV, где он будет далее использоваться для синхронизации с базой данных , Я использовал код Powershell, чтобы извлечь xml в хэш. Теперь у меня проблема с преобразованием их в CSV. Export-csv записывает только последнюю запись в хеш. Не знаю, почему это, я проверил несколько других форумов, они говорят, что функция -append в Export-csv только с powershell 3.0, я использую 1.0 ..Powershell XML Export-csv не добавляет Hash

вы можете мне помочь?

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

У вас есть несколько проблем здесь. 1-й, вы создаете массив 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 + = New-Object PSObject -Property @ {SegmentName = $ segname Host = $ hostname.InnerText}' @Graimer: Это было здорово! работал отлично .. Но я хочу узнать больше. Будете ли вы добрыми некоторыми из моих основных вопросов? Исправьте меня, если я ошибаюсь. –

+0

Мои вопросы на линии, о которой я упомянул. Сначала я понимаю + = добавляет элементы в массив, это единственный способ их добавить? .. Когда я печатаю свой $ MasterArray, почему он сначала печатает хост-столбец, а затем имя segementname. Мне жаль, если это основные вопросы, я хочу узнать из основ этого. –

+0

'+ =' - лучший способ. У вас есть метод под названием «Добавить()», но он всегда будет терпеть неудачу. Массивы являются фиксированными размерами и не могут добавлять элементы. Чтобы добавить элементы, вам нужно создать новый массив, содержащий значения старого массива и новое значение (это делается в памяти), а затем сохранить его как переменную (например, перезаписать старый массив). Вот что делает '+ ='. Массивы не имеют фиксированного порядка столбцов, поэтому вывод «случайный». Используйте '$ array | Format-Table (или Format-List) -Property Column1, Column2 и т. Д., Чтобы указать ваш заказ. Если у вас есть еще вопросы, выполните поиск здесь. Ответ на большинство основных вопросов. –

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' - как это будет называться? Массив, хашаррей, многомерный массив? –

+0

«Лучший» способ - это то, как вы предпочитаете. xpath и «путь собственности» (например, выше) все делают то же самое.В этом случае '$ myArray = @()', то он называется «массивом» –

+0

Как подразумевает Греймер, существует множество «лучших» способов делать вещи. Вы хотите, чтобы наиболее читаемые, лучшие, или что? Я склоняюсь к удобочитаемости, если только я не нашел конкретного узкого места. Однако читаемость очень субъективна, в зависимости от того, с чем вы уже знакомы. – KevinD

Смежные вопросы