简体   繁体   English

在Power Shell中将xml转换为csv

[英]Convert xml to csv in Power shell

Hello I am new to Powershell, but I have looked all over for an answer to this question, how do I convert XML data to CSV data in powershell? 您好,我是Powershell的新手,但是到处都在寻找这个问题的答案,如何在Powershell中将XML数据转换为CSV数据?

Here is my xml file: 这是我的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>

The fields that are multiple layers in the tree are the biggest pain. 树上多层的字段是最大的麻烦。 Here is the script I have come up with so far. 这是到目前为止我提出的脚本。 I am able to get the basic fields such as name and email. 我可以获取基本字段,例如姓名和电子邮件。 I really need the fields that are labeled custom fields and their subsets. 我确实需要标记为自定义字段及其子集的字段。

#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 output file should look something like this. CSV输出文件应如下所示。 (see attached) (见附件)

CSV Output File CSV输出文件

Any help is greatly appreciated! 任何帮助是极大的赞赏!

Thanks 谢谢

You would need to generate an object, similarly to how you are doing it now, but you would need to add properties to it for each custom field before outputting it. 您将需要生成一个对象,类似于现在的操作,但是需要在输出每个自定义字段之前向其添加属性。 The only complication comes in if you have users with different custom fields. 如果您的用户具有不同的自定义字段,唯一的麻烦就来了。 Since PowerShell won't output any properties that the first item in your array has you have to find all potential properties, and add them to the first object. 由于PowerShell不会输出任何属性,因此数组中的第一项必须具有所有潜在的属性,然后将它们添加到第一个对象中。 This should do what you want I'm fairly sure. 我相当确定这应该做您想要的。 I've added a second user to the XML with a different custom field (replaced 60019 with 60034) to show the output. 我向XML中添加了另一个用户,该用户具有不同的自定义字段(将60019替换为60034)以显示输出。

[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 *

The output of that is: 输出为:

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"

You could just as easily pipe $Results to Export-Csv if you need it output to a file. 如果您需要将$Results输出到文件中,也可以很容易地Export-Csv其输出到Export-Csv

Here's my alteration of TheMadTechnician's answer , with necessary explaining comments: 这是我对TheMadTechnician答案的修改, 并附有必要的解释性注释:

$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

Input (modified original XML ); 输入 (修改后的原始XML ); entered separately to avoid vertical scrolling in above code: 为避免在上面的代码中垂直滚动而单独输入:

$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>
'@

Output : 输出

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"

Note in regard of Tomalak's useful comment stating that XML files should always be read using the XmlDocument object's .Load() method . 关于Tomalak的有用注释请注意应该始终使用XmlDocument对象的.Load()方法读取XML文件

###                   $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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM