在Power shell中将xml转换为csv

时间:2017-12-05 18:56:11

标签: xml powershell csv

您好我是Powershell的新手,但我已经全神贯注地回答了这个问题,如何在PowerShell中将XML数据转换为CSV数据?

这是我的xml文件:

<users>
     <user>
        <id>"data"</id>
        <name>"data"</name>
        <disabled>"data"</disabled>
        <title>"data"</title>
        <email>"data"</email>
        <role>
             <name>"data"</name>
        </role>
        <custom_fields_values>
            <custom_fields_value>
                <custom_field_id>60019</custom_field_id>
                <value>"data"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60021</custom_field_id>
                <value>"data"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60018</custom_field_id>
                <value>"data"</value>
            </custom_fields_value>
        </custom_fields_values>
        <site>
            <name>"data"</name>
        </site>
    </user>
</users>

树中多层的字段是最大的痛苦。这是我到目前为止提出的脚本。我能够获得名称和电子邮件等基本字段。我真的需要标记自定义字段及其子集的字段。

#Converts the xml to a CSV file 
$samage_users.users.user | select-Object @(
@{l="Email";e={$_.email}},
@{l="Name";e={$_.name}},
@{l="ID";e={$_.ID}},
@{l="Phone";e={$_.phone}},
@{l="Site";e={$_.site.name}},
@{l="Reports_To";e={$_.reports_to.name}},
@{l="Reports_To_Email";e={$_.reports_to.email}})|
export-csv "Samanage_users.csv" -NoTypeInformation -Append
$page ++
start-sleep -s 10
}
While ($page -lt ($pages + 2))
}
Function NewUsers
{
foreach ($user in $new_user)
{

CSV输出文件应该如下所示。 (见附件)

CSV Output File

非常感谢任何帮助!

由于

2 个答案:

答案 0 :(得分:2)

您需要生成一个对象,类似于您现在的操作方式,但在输出之前,您需要为每个自定义字段添加属性。如果您的用户具有不同的自定义字段,则唯一的复杂功能就在于此。由于PowerShell不会输出数组中第一个项目的任何属性,因此您必须找到所有可能的属性,并将它们添加到第一个对象。这应该做你想要的我相当肯定。我已经使用不同的自定义字段(用60034替换60019)向XML添加了第二个用户以显示输出。

[xml]$samage_users=@'
<users>
        <user>
        <id>"data"</id>
        <name>"data"</name>
        <disabled>"data"</disabled>
        <title>"data"</title>
        <email>"data"</email>
        <role>
                <name>"data"</name>
        </role>
        <custom_fields_values>
            <custom_fields_value>
                <custom_field_id>60019</custom_field_id>
                <value>"data"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60021</custom_field_id>
                <value>"data"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60018</custom_field_id>
                <value>"data"</value>
            </custom_fields_value>
        </custom_fields_values>
        <site>
            <name>"data"</name>
        </site>
    </user>
    <user>
        <id>"data2"</id>
        <name>"data2"</name>
        <disabled>"data2"</disabled>
        <title>"data2"</title>
        <email>"data2"</email>
        <role>
                <name>"data2"</name>
        </role>
        <custom_fields_values>
            <custom_fields_value>
                <custom_field_id>60021</custom_field_id>
                <value>"data2"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60018</custom_field_id>
                <value>"data2"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60034</custom_field_id>
                <value>"data2"</value>
            </custom_fields_value>
        </custom_fields_values>
        <site>
            <name>"data2"</name>
        </site>
    </user>
</users>
'@

$Results = ForEach($User in $samage_users.users.user) {
    $UserObject = [PSCustomObject][ordered]@{
        "Email" = $User.email
        "Name" = $User.name
        "ID" = $User.ID
        "Phone" = $User.phone
        "Site" = $User.site.name
        "Reports_To" = $User.reports_to.name
        "Reports_To_Email" = $User.reports_to.email
    }
    $User.custom_fields_values.custom_fields_value | ForEach {Add-Member -InputObject $UserObject -NotePropertyName $_.custom_field_id -NotePropertyValue $_.value}
    $UserObject
}
$Results | ForEach{ $_.PSObject.Properties.Name }| Select -Unique | Where{ $_ -notin $Results[0].PSObject.Properties.Name } | ForEach{ Add-Member -InputObject $Results[0] -NotePropertyName $_ -NotePropertyValue ' ' }
$Results | FT *

输出是:

Email   Name    ID      Phone Site    Reports_To Reports_To_Email 60019  60021   60018   60034  
-----   ----    --      ----- ----    ---------- ---------------- -----  -----   -----   -----  
"data"  "data"  "data"        "data"                              "data" "data"  "data"         
"data2" "data2" "data2"       "data2"                                    "data2" "data2" "data2"

如果需要输出到文件,您可以轻松地将$Results传送到Export-Csv

答案 1 :(得分:0)

这是我对TheMadTechnician's answer的更改,并附有必要的解释说明:

$RObj = ForEach ($User in $samage_users.users.user) { 
  ### calculate basic properties - even those ones absent in XML
  $UObj = $user | Select-Object @(
    @{l="Email";e={$_.email}},
    @{l="Name";e={$_.name}},
    @{l="ID";e={$_.ID}},
    @{l="Phone";e={$_.phone}},
    @{l="Site";e={$_.site.name}},
    @{l="Rs_To";e={$_.reports_to.name}},   # "Rs_To"   cut "Reports_To"
    @{l="Rs_To_E";e={$_.reports_to.email}} # "Rs_To_E" cut "Reports_To_Email"
                                           # cuttings merely for better output readability
  )
  ### add user-dependent properties for each custom field 
    $User.custom_fields_values.custom_fields_value | 
      ForEach-Object {
        $UObj | Add-Member NoteProperty -Name $_.custom_field_id -Value $_.value
      }
    $UObj     ### add current PSCustomObject to the `$RObj` array
}
### mutually arrange potentially missing user-dependent properties
for ($i = 0; $i -lt $RObj.Count; $i++ ) {
 for ($j = 0; $j -lt $RObj.Count; $j++ ) {
  if ( $i -ne $j ) {
   $RObj[$i] | ForEach-Object { $_.PSObject.Properties.Name } | 
    Where-Object { $_ -notin $RObj[$j].PSObject.Properties.Name } | 
     ForEach-Object { 
        $RObj[$j] | Add-Member -MemberType NoteProperty -Name $_ -Value ''
     }
  }
 }
}
### $RObj | Export-Csv "Samanage_users.csv" -NoTypeInformation
### debugging output instead of `Export-Csv`
$RObj | Format-Table -Property * -AutoSize

输入(修改后的原始XML);单独输入以避免在上面的代码中垂直滚动:

$samage_users=[xml]@'
<?xml version="1.0" encoding="UTF-8"?>
<users>
        <user>
        <id>"dI"</id>
        <name>"dN"</name>
        <disabled>"dD"</disabled>
        <title>"dT"</title>
        <email>"dE"</email>
        <role>
                <name>"dR"</name>
        </role>
        <custom_fields_values>
            <custom_fields_value>
                <custom_field_id>60044</custom_field_id>
                <value>"dC1"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60021</custom_field_id>
                <value>"dC2"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60018</custom_field_id>
                <value>"dC3"</value>
            </custom_fields_value>
        </custom_fields_values>
        <site>
            <name>"dSi"</name>
        </site>
    </user>
    <user>
        <id>"d2I"</id>
        <name>"d2N"</name>
        <disabled>"d2D"</disabled>
        <title>"d2T"</title>
        <email>"d2E"</email>
        <role>
                <name>"d2R"</name>
        </role>
        <Reports_To>
            <name>"d2RTn"</name>
            <email>"d2RTe"</email>
        </Reports_To>
        <custom_fields_values>
            <custom_fields_value>
                <custom_field_id>60021</custom_field_id>
                <value>"d2C1"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60018</custom_field_id>
                <value>"d2C2"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60034</custom_field_id>
                <value>"d2C3"</value>
            </custom_fields_value>
        </custom_fields_values>
        <site>
            <name>"d2Si"</name>
        </site>
    </user>
    <user>
        <id>"d3I"</id>
        <name>"d3N"</name>
        <disabled>"d3D"</disabled>
        <title>"d3T"</title>
        <email>"d3E"</email>
        <role>
                <name>"d3R"</name>
        </role>
        <custom_fields_values>
            <custom_fields_value>
                <custom_field_id>60055</custom_field_id>
                <value>"d3C1"</value>
            </custom_fields_value>
            <custom_fields_value>
                <custom_field_id>60066</custom_field_id>
                <value>"d3C2"</value>
            </custom_fields_value>
        </custom_fields_values>
        <site>
            <name>"d3Si"</name>
        </site>
    </user>
</users>
'@

<强>输出

PS D:\PShell D:\PShell\SO\47660787.ps1

Email Name  ID    Phone Site   Rs_To   Rs_To_E 60044 60021  60018  60034  60055  60066 
----- ----  --    ----- ----   -----   ------- ----- -----  -----  -----  -----  ----- 
"dE"  "dN"  "dI"        "dSi"                  "dC1" "dC2"  "dC3"                      
"d2E" "d2N" "d2I"       "d2Si" "d2RTn" "d2RTe"       "d2C1" "d2C2" "d2C3"              
"d3E" "d3N" "d3I"       "d3Si"                                            "d3C1" "d3C2"

注意关于Tomalak's useful comment声明应始终使用XmlDocument对象的.Load()方法读取XML文件。< / p>

###                   $samage_users defined as above i.e. a herestring cast to [xml] type
$xml = New-Object Xml
$xml.Load("Samanage_users.xml")            ### a file containing above herestring content
Compare-Object $samage_users.InnerXml $xml.InnerXml                     ### no difference