2017-12-05 37 views
0

Hallo Ich bin neu in Powershell, aber ich habe überall nach einer Antwort auf diese Frage, wie konvertiere ich XML-Daten in CSV-Daten in Powershell?Convert xml in csv in Power-Shell

Hier ist meine XML-Datei:

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

Die Felder, die mehrere Ebenen in dem Baum sind der größte Schmerz sind. Hier ist das Skript, das ich bisher gefunden habe. Ich kann die grundlegenden Felder wie Name und E-Mail abrufen. Ich brauche wirklich die Felder, die benutzerdefinierte Felder und ihre Untergruppen bezeichnet werden.

#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-Ausgabedatei sollte in etwa so aussehen. (Siehe beigefügte)

CSV Output File

Jede Hilfe wird sehr geschätzt!

Dank

+0

Zeigen Sie auch die gewünschte Ausgabe an. – Tomalak

+0

Ich habe Korrekturen an meinem Beitrag vorgenommen. –

+0

Wirklich? Sie möchten für jedes dieser Felder "CUSTOM FIELD ID" gefolgt von "CUSTOM FIELD VALUE" und nicht nur die Spalte "60019" mit dem entsprechenden Wert? – TheMadTechnician

Antwort

0

Hier ist meine Veränderung TheMadTechnician's answer, mit der notwendigen Erklärung Kommentare:

$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 

Eingang (modifizierte Original XML); gesondert gestellt vertikales Scrollen in obigem Code zu vermeiden:

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

Ausgang:

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" 

Hinweis hinsichtlich der Tomalak's useful comment Angabe , dass XML-Dateien sollten immer mit dem .Load() Methode des XmlDocument Objekts gelesen werden.

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

Sie müßten ein Objekt zu erzeugen, ähnlich wie Sie es jetzt tun, aber Sie würden für jedes benutzerdefiniertes Feld Eigenschaften, um es hinzuzufügen müssen, bevor es ausgegeben wird. Die einzige Komplikation tritt auf, wenn Sie Benutzer mit verschiedenen benutzerdefinierten Feldern haben. Da PowerShell keine Eigenschaften ausgibt, die das erste Element in Ihrem Array enthält, müssen Sie alle potenziellen Eigenschaften finden und sie zum ersten Objekt hinzufügen. Das sollte tun was du willst bin mir ziemlich sicher. Ich habe dem XML einen zweiten Benutzer mit einem anderen benutzerdefinierten Feld hinzugefügt (60019 durch 60034 ersetzt), um die Ausgabe anzuzeigen.

[xml][email protected]' 
<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 * 

Der Ausgang davon ist:

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" 

Sie könnten genauso gut Rohr $Results zu Export-Csv wenn Sie es brauchen Ausgabe in eine Datei.

+0

Es ist erwähnenswert, dass XML-Dateien immer mit der Methode '.Load()' des 'XmlDocument' -Objekts gelesen werden sollten (im Gegensatz zu' Get-Content' plus explizite '[xml]' cast, die oft verwendet wird, aber falsch ist) . – Tomalak

+0

Add-Mitglied: Das Argument für den Parameter 'NotePropertyName' kann nicht validiert werden. Das Argument ist null oder leer. Geben Sie ein -Argument an, das nicht null oder leer ist, und wiederholen Sie dann den Befehl. Bei C: \ Benutzer \ dyl201 \ Desktop \ uploadusers.ps1: 50 Zeichen. 117 + ... -InputObject $ Benutzerobjekt -NotePropertyName $ _ custom_field_id -NotePr ... + ~~~~~~~~~ ~~~~~~~~ + CategoryInfo: InvalidData: (:) [Add-Mitglied], ParameterBindingValidationException + FullyQualifiedErrorId: ParameterArgumentValidationError, Microsoft.PowerShell.Commands.AddMemberCommand –

+0

Das war der Fehler, den ich bekam, als ich meine ersetzte Teil des Skripts mit allem, was bei $ results beginnt. Es ist auch für diese gestellt: Cmdlets Export-Csv an Kommando-Pipeline Position 1 Versorgungs Werte für die folgenden Parameter: Inputobject: –