springstil
Goto Top

Powershell: CSV zu XML

Hallo zusammen,

ich hab das folgendes Problem:


Ich möchte gerne aus einer CSV Datei (dort sind bestände drin) gerne eine XML Datei Generieren.. Grundsätzlich ja nicht das Problem, allerdings macht mir das Format der XML zu schaffen..

Ich würde das ganze am liebsten in Powershell umsetzen.
Das Schema sieht so aus:
<?xml version="1.0" encoding="UTF-8"?>  
<MessageList
        xmlns="http://schema.limango.de"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xsi:schemaLocation="http://schema.limango.de  
                            http://schema.limango.de/merchant/messagelist.xsd" 
        created="2019-01-15T15:52:01+00:00"  
        version="1.0">  
        <Message type="stock-amount">  
        <MerchantVariantID>sss-444-44</MerchantVariantID>
        <Amount>12345</Amount>
    </Message>
</MessageList>
 


created würde einfach immer nur das Aktuelle Datum / zeit sein, der Rest wie MerchantVariantID und MerchantVariantID wären in der CSV zu finden.

die xsd dazu hätte ich auch. Nur reichen meine einfachen Kenntnisse in PowerShell und kaum Kenntnisse in XML nicht aus.

Ich hoffe jemand kann mir hierbei weiterhelfen.

Content-ID: 617237

Url: https://administrator.de/contentid/617237

Ausgedruckt am: 24.11.2024 um 10:11 Uhr

Springstil
Springstil 30.10.2020 um 08:54:12 Uhr
Goto Top
Danke für die Antwort, leider hilft mir die nur bedingt.

Ich habe zur zeit von @colinardo folgendes Skript genutzt und etwas umgeschrieben.

param(
    [string]$folder,
    [string]$delimiter = ";"  
)
# Alle CSV-Dateien des Ordners durchlaufen
gci $folder -Filter "*.csv" | %{  
    write-host "Konvertiere '$($_.Fullname)' ..." -ForegroundColor Green  
    # importiere CSV-Datei als Objekt
    $csv = import-csv $_.Fullname -Delimiter $delimiter
    # Spaltennamen der CSV-Datei extrahieren
    $cols = $csv | gm -MemberType NoteProperty | select -ExpandProperty Name
    # erzeuge neues XML-Dokument
    $xml = New-Object XML
    # XML Grundgerüst laden
    $xml.LoadXml('<?xml version="1.0" encoding="utf-8"?><MessageList>xmlns="http://schema.limango.de"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xsi:schemaLocation="http://schema.limango.de  
                            http://schema.limango.de/merchant/messagelist.xsd" 
        created="2019-01-15T15:52:01+00:00"  
        version="1.0">  
   </MessageList>')  
    # Root-Knoten referenzieren
    $MessageList = $xml.SelectSingleNode("/MessageList")  
    # für jede Zeile der CSV-Datei ...
    foreach($line in $csv){
        # erzeuge ein neues Row-Element
        $row = $xml.CreateElement("row")  
        # für jede Spalte der Zeile erstelle ein neues Element mit dem Namen der Spalte und dem Inhalt der aktuellen Zeile
        $cols | %{
            $col = $xml.CreateElement($_)
            $col.InnerText = $line.($_)
            $row.AppendChild($col) | out-null
        }
        # füge das Row-Element im Root-Knoten ein
        $MessageList.AppendChild($row) | out-null
    }
    # Speichere die neue XML-Datei
    $xml.Save($_.DirectoryName + "\" + $_.BaseName + ".xml")  
}

Der Anfang sieht schon mal ganz gut aus, nur müsste z.b anstelle von
row
dort
Message type="stock-amount"  
stehen und am ende dann halt
</Message>


Nur wie bekomme ich das geregelt ?
colinardo
Lösung colinardo 30.10.2020 aktualisiert um 14:57:24 Uhr
Goto Top
Servus, willkommen auf Administrator.de!
Nur wie bekomme ich das geregelt ?
Sofern der Aufbau der CSV so aussieht
"MerchantVariantID";"Amount"  
"sss-444-44";"100.12"  
"sss-555-44";"100.55"  
sieht das für den obigen Code so aus:
param(
    [string]$folder,
    [string]$delimiter = ";"  
)
# Alle CSV-Dateien des Ordners durchlaufen
gci $folder -Filter "*.csv" | %{  
    $newname = $_.DirectoryName + "\" + $_.BaseName + ".xml"  
    write-host "Konvertiere '$($_.Fullname)' in '$newname'." -ForegroundColor Green  
    # importiere CSV-Datei als Objekt
    $csv = import-csv $_.Fullname -Delimiter ";"  
    # Spaltennamen der CSV-Datei extrahieren
    $cols = $csv | gm -MemberType NoteProperty | select -ExpandProperty Name
    # erzeuge neues XML-Dokument
    $xml = New-Object XML
    # XML Grundgerüst laden
    $xml.LoadXml('<?xml version="1.0" encoding="utf-8"?><MessageList xmlns="http://schema.limango.de" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.limango.de http://schema.limango.de/merchant/messagelist.xsd" created="" version="1.0" />')  
    # Zeit im 'created' Attribut des Document-Root setzen 
    $xml.DocumentElement.created = [string](get-date -f s)
    # für jede Zeile der CSV-Datei ...
    foreach($line in $csv){
        # erzeuge ein neues Message-Element mit dem Standard-Namespace
        $row = $xml.CreateElement('Message','http://schema.limango.de')  
        # füge dem Message Element ein Attribut hinzu
        $row.SetAttribute('type','stock-amount')  
        # für jede Spalte der Zeile erstelle ein neues Element mit dem Namen der Spalte und dem Inhalt der aktuellen Zeile
        $cols | %{
            $col = $xml.CreateElement($_,'http://schema.limango.de')  
            $col.InnerText = $line.($_)
            $row.AppendChild($col) | out-null
        }
        # füge das Message-Element im Root-Knoten ein
        $xml.DocumentElement.AppendChild($row) | out-null
    }
    # Speichere die neue XML-Datei
    $xml.Save($newname)
}
Grüße Uwe
Springstil
Springstil 30.10.2020 aktualisiert um 20:15:33 Uhr
Goto Top
Mein Held!!! Vielen Vielen lieben dank !!!

Läuft super! Einzige was mir auffällt ist das er zuerst spalte 2 nimmt und dann 1 also quasi

<?xml version="1.0" encoding="utf-8"?>  
<MessageListList xmlns="http://schema.limango.de" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.limango.de&#xD;&#xA;                            http://schema.limango.de/merchant/messagelist.xsd" created="2020-10-30T20:14:41" version="1.0">  
  <Message type="stock-amount">  
    <Amount>500</Amount>
    <MerchantVariantID>471145-50</MerchantVariantID>
  </Message>
  <Message type="stock-amount">  
    <Amount>900</Amount>
    <MerchantVariantID>98541-31</MerchantVariantID>
  </Message>
</MessageListList>

aber das sollte nicht weiterschlimm sein da der inhalt stimmt oder?
colinardo
Lösung colinardo 30.10.2020 aktualisiert um 21:54:03 Uhr
Goto Top
Das ist kein Problem, deswegen ist es ja XML, dem ist die Reihenfolge egal Hauptsache der Name des Knotens stimmt und folgt den Bestimmungen der Schemadefinition, du kannst die Reihenfolge aber auch selbst bestimmen indem du die Spaltennamen welche
in dieser Zeile automatisch extrahiert werden sortierst wenn du unbedingt willst
$cols = $csv | gm -MemberType NoteProperty | sort Name -Descending | select -ExpandProperty Name
Wenn du sowieso nur zwei Spalten hast könntest du auch auf die automatische Extrahierung der Spaltennamen verzichten, das war ja in dem Skript nur dafür vorgesehen daß es universell anwendbar ist.
Springstil
Springstil 30.10.2020 um 22:02:16 Uhr
Goto Top
Einfach genial. Ich danke dir recht herzlich!! Wenn dass mein EDI Dienstleister hätte konvertieren müssen, hätte ich dafür 1400 Euro zahlen müssen.. So mach ich das ganze einfach selber. Vielen lieben dank nochmal face-smile
colinardo
colinardo 30.10.2020 um 22:03:41 Uhr
Goto Top
Immer gerne, freut mich wenn's hilft. 🙂

Schönes Wochenende.
Grüße Uwe