【问题标题】:Powershell XML Export-csv not appending a HashPowershell XML Export-csv 不附加哈希
【发布时间】:2013-02-05 13:27:18
【问题描述】:

我是 Powershell 的新手,我的 xml 很奇怪,我的主要目标是将 XML 转换为 CSV,在那里它将进一步用于同步到数据库。 我已经使用 Powershell 代码将 xml 提取到哈希中。 现在我在将它们转换为 CSV 时遇到问题。 Export-csv 仅写入散列中的最后一个条目。不知道为什么,我检查了其他几个论坛,他们说 Export-csv 中的 -append 功能仅适用于 powershell 3.0,我使用的是 1.0..

你能帮我解决这个问题吗?

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"

【问题讨论】:

    标签: c# .net powershell powershell-2.0 powershell-remoting


    【解决方案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
    

    【讨论】:

    • 非常感谢,效果很好..您已经最小化了代码行,这使得它更有效率..但只是想知道解析 xml 的最佳方法,我在其中看到了很多方法stackoverflow .. $myArray - 这叫什么?数组、哈希数组、多维数组??
    • “最佳”方式是您喜欢的方式。 xpath 和“属性方式”(如上面的)都做同样的事情。在这种情况下,$myArray = @(),则称为“数组”
    • 正如 Graimer 所暗示的,有多种“最佳”的做事方式。你想要最易读、性能最好的,还是什么?我倾向于支持可读性,除非我发现了一个特定的瓶颈。但是,可读性是非常主观的,取决于您已经熟悉的内容。
    • 嘿@KevinD & Graimer ..需要对此做些小改动..我想将 CSV 的标题重命名为“段名”和“主机名”..这可能吗..就像更改Array变量名一样,变量名不能包含空格..请尽快回复,需要在今晚之前提交..
    • 查看更新的答案。如果您阅读了代码,您可能已经知道自己在哪里进行更改。请至少在询问之前尝试。您通常需要调整您在 SO 上获得的解决方案以适应您的情况。我们不是咨询公司。 ^^
    【解决方案2】:

    这里有多个问题。首先,您创建一个数组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"
    

    【讨论】:

    • $MasterArray += New-Object psobject -Property @{ SegmentName = $segname Host = $hostname.InnerText } @Graimer :太棒了!工作完美..但我想了解更多。你能回答我的一些基本问题吗?如果我错了,请纠正我..
    • 我的问题就在我提到的那一行。首先我明白 += 将元素添加到数组中,这是添加它们的唯一方法吗??.. 当我打印我的 $MasterArray 时,为什么它是否先打印主机列然后打印段名。如果这些是基本问题,我很抱歉,我希望从这个基础知识中学习。
    • += 是最好的方法。您有一个名为Add() 的方法,但它总是会失败。数组是固定大小的,不能添加元素。要添加元素,您需要创建一个包含旧数组值和新值的新数组(这是在内存中完成的),然后将其保存为变量(例如覆盖旧数组)。这就是+= 所做的。数组没有固定的列顺序,因此输出是“随机的”。使用$array | Format-Table(or Format-List) -Property Column1, Column2 etc. 设置您的订单。如果您有更多问题,请在此处搜索 SO。最基本的问题都已经回答过了。
    • 嘿@KevinD & Graimer ..需要对此做些小改动..我想将CSV的标题重命名为“段名”和“主机名”..这可能吗..就像更改数组变量名一样,变量名不能包含空格..请尽快回复,需要在今晚之前提交..
    • 查看更新的答案。属性可以包含空格,只需引用名称即可,例如$object.'This Property'
    猜你喜欢
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 2021-05-29
    • 2020-06-28
    • 1970-01-01
    • 2018-01-22
    相关资源
    最近更新 更多