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-Key: 617237

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

Printed on: April 25, 2024 at 10:04 o'clock

Member: erikro
erikro Oct 29, 2020 at 22:18:24 (UTC)
Goto Top
Member: Springstil
Springstil Oct 30, 2020 at 07:54:12 (UTC)
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 ?
Member: colinardo
Solution colinardo Oct 30, 2020 updated at 13:57:24 (UTC)
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
Member: Springstil
Springstil Oct 30, 2020 updated at 19:15:33 (UTC)
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?
Member: colinardo
Solution colinardo Oct 30, 2020 updated at 20:54:03 (UTC)
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.
Member: Springstil
Springstil Oct 30, 2020 at 21:02:16 (UTC)
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
Member: colinardo
colinardo Oct 30, 2020 at 21:03:41 (UTC)
Goto Top
Immer gerne, freut mich wenn's hilft. 🙂

Schönes Wochenende.
Grüße Uwe