Csv in XML mit Powershell
Hallo zusammen,
was ich mittlerweile einigermaßen kann, ist es XML in CSV umzuwandeln mit Hilfe von PowerShell
Mir ist auch schon bei einer anderen CSV zu XML geholfen worden, allerdings komme ich hier gerade nicht wirklich weiter da ich nicht genau weiß wie ich mein Bestehendes Skript ändern solle.
Das Beispiel sieht so aus:
Mir geht es um die Felder:
GTIN
Channel SKU
INV_COUNT
QUANTITY_UNIT
DATETIME
DATE (nur wenn INV_COUNT auf 0 ist wenn sowas geht / oder das Feld gefüllt ist)
Ich hoffe mir kann bei dem Skript jemand helfen
was ich mittlerweile einigermaßen kann, ist es XML in CSV umzuwandeln mit Hilfe von PowerShell
Mir ist auch schon bei einer anderen CSV zu XML geholfen worden, allerdings komme ich hier gerade nicht wirklich weiter da ich nicht genau weiß wie ich mein Bestehendes Skript ändern solle.
Das Beispiel sieht so aus:
Mir geht es um die Felder:
GTIN
Channel SKU
INV_COUNT
QUANTITY_UNIT
DATETIME
DATE (nur wenn INV_COUNT auf 0 ist wenn sowas geht / oder das Feld gefüllt ist)
Ich hoffe mir kann bei dem Skript jemand helfen
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 665676
Url: https://administrator.de/forum/csv-in-xml-mit-powershell-665676.html
Ausgedruckt am: 22.12.2024 um 11:12 Uhr
11 Kommentare
Neuester Kommentar
Servus @Springstil,
habe dir alle Zeilen diesmal noch ausführlich kommentiert, damit nach dem Lesen das Verfahren nun klar geworden sein sollte und du in Zukunft bei neuen Aufgaben darauf aufbauen kannst (hoffentlich ).
Das Prinzip ist eigentlich immer gleich. Und zwar musst du die Knoten einerseits alle mit dem xmlns Namepace der im Document-Root definiert ist erstellen (dazu war die Variable $ns im Kopf gedacht).
Das was du auch verstehen musst, ist die Reihenfolge in der du die Knoten einhängen musst. Dies geschieht immer vom am tiefsten verschachtelten Knoten aus gesehen nach oben. die Kinder werden dann in den nächst höheren Knoten "eingehängt" danach wird dieser Knoten wieder an seinem "Parent" eingehängt, bis man am Document(Root)-Knoten des Trees angekommen ist. Hier im Beispiel sind also die letzten Knoten die man einhängt der INVENTORIES Knoten und der SUPPLIER_ID Knoten die beide sogenannte "Sibblings"(benachbarte Knoten) im Document-Knoten darstellen.
Außerdem solltest du beachten das XML Dokumente Case-Sensitive sind, also ein Element mit dem Namen "Supplier_Id" ist nicht gleich "SUPPLIER_ID", das sind in XML-Syntax zwei gänzlich unterschiedliche Elemente.
Ich würde dir auch mal ans Herz legen dich in die Grundlagen von XML Dokumenten einzuarbeiten dann verstehst du das mit den Namespaces auch besser. Auch wenn die Materie trocken anmutet, du wirst sehen sie hilft dir jedes mal wenn du mit XML-Dateien hantieren musst. Und so viel gibt es da auch nicht zu verstehen.
https://www.data2type.de/xml-xslt-xslfo/xml/xml-in-a-nutshell/xml-grundl ...
Zusätzlich die Dokumentation zum XMLDocument-Object seinen Methoden und Eigenschaften auch ganz hilfreich für die Powershell da das die selben Objekte sind
https://docs.microsoft.com/de-de/dotnet/api/system.xml.xmldocument?view= ...
Hope this helps
Viel Erfolg.
Grüße Uwe
habe dir alle Zeilen diesmal noch ausführlich kommentiert, damit nach dem Lesen das Verfahren nun klar geworden sein sollte und du in Zukunft bei neuen Aufgaben darauf aufbauen kannst (hoffentlich ).
Das Prinzip ist eigentlich immer gleich. Und zwar musst du die Knoten einerseits alle mit dem xmlns Namepace der im Document-Root definiert ist erstellen (dazu war die Variable $ns im Kopf gedacht).
Das was du auch verstehen musst, ist die Reihenfolge in der du die Knoten einhängen musst. Dies geschieht immer vom am tiefsten verschachtelten Knoten aus gesehen nach oben. die Kinder werden dann in den nächst höheren Knoten "eingehängt" danach wird dieser Knoten wieder an seinem "Parent" eingehängt, bis man am Document(Root)-Knoten des Trees angekommen ist. Hier im Beispiel sind also die letzten Knoten die man einhängt der INVENTORIES Knoten und der SUPPLIER_ID Knoten die beide sogenannte "Sibblings"(benachbarte Knoten) im Document-Knoten darstellen.
Außerdem solltest du beachten das XML Dokumente Case-Sensitive sind, also ein Element mit dem Namen "Supplier_Id" ist nicht gleich "SUPPLIER_ID", das sind in XML-Syntax zwei gänzlich unterschiedliche Elemente.
# CSV Dateien in Array lesen
$files = ls '\\10.173.45.12\sog\Bestandsupload\klingel' -File -Filter *.csv
# Default Namespace für Elemente definieren == der Wert der "xmlns"-Property des INVRPT Knotens
# Alle Knoten die diesen Namespace erben sollen müssen mit diesem Namespace als zweitem Parameter erstellt werden
$ns = "http://www.kmopartnerb2b.com"
foreach($file in $files){
$xml = [xml]'<?xml version="1.0" encoding="utf-8" ?><INVRPT xmlns="http://www.kmopartnerb2b.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" />'
# SUPPLIER_ID -Knoten erstellen
$supplier_id = $xml.CreateElement("SUPPLIER_ID",$ns)
# und festen Wert zuweisen
$supplier_id.innerText = '123456'
# INVENTORIES -Knoten erstellen
$inventories = $xml.CreateElement("INVENTORIES",$ns)
# INVENTORY_UPDATE -Knoten erstellen
$inventory_update = $xml.CreateElement("INVENTORY_UPDATE",$ns)
# CSV einlesen und aus den Zeilen ITEM-Knoten erstellen
Import-CSV $file.FullName -Delimiter ";" | %{
write-host "Verarbeite '$($file.Fullname)' ..."
# ITEM-Knoten erstellen
$itm = $xml.CreateElement("ITEM",$ns)
# SUPPLIER_SKU_ID-Knoten erstellen
$SUPPLIER_SKU_ID = $xml.CreateElement("SUPPLIER_SKU_ID",$ns)
$SUPPLIER_SKU_ID.InnerText = $_.SUPPLIER_ID
$itm.AppendChild($SUPPLIER_ID)
# CHANNEL_SKU-Knoten erstellen
$CHANNEL_SKU = $xml.CreateElement("CHANNEL_SKU",$ns)
$CHANNEL_SKU.InnerText = $_.CHANNEL_SKU
$itm.AppendChild($CHANNEL_SKU)
# INV_COUNT-Knoten erstellen
$INV_COUNT = $xml.CreateElement("INV_COUNT",$ns)
$INV_COUNT.InnerText = $_.INV_COUNT
$itm.AppendChild($INV_COUNT)
# QUANTITY_UNIT-Knoten erstellen
$QUANTITY_UNIT = $xml.CreateElement("QUANTITY_UNIT",$ns)
$QUANTITY_UNIT.InnerText = $_.QUANTITY_UNIT
$itm.AppendChild($QUANTITY_UNIT)
# wenn INV_COUNT Spalte der CSV nicht leer DATETIME Knoten erstellen
if ($_.INV_COUNT -ne ''){
$Datetimes = $xml.CreateElement("DATETIME",$ns)
$Date = $xml.CreateElement("DATE",$ns)
$Date.innerText = $_.Date
$Datetimes.AppendChild($Date)
$time = $xml.CreateElement("TIME",$ns)
$time.innerText = $_.time
$Datetimes.AppendChild($time)
$itm.AppendChild($Datetimes)
}
# Wenn TERM Spalte der CSV nicht leer ist TERM Knoten hinzufügen
if ($_.Term -ne ''){
$TERM = $xml.CreateElement("TERM",$ns)
$TERM.InnerText = $_.TERM
$itm.AppendChild($TERM)
}
# ITEM-Knoten in INVENTORY_UPDATE-Knoten anhängen
$inventory_update.AppendChild($itm) | out-null
} | out-null
# INVENTORY_UPDATE Knoten im INVENTORIES Knoten einhängen
$inventories.AppendChild($inventory_update) | out-null
# SUPPLIER_ID Knoten in den Root-Knoten einhängen
$xml.DocumentElement.AppendChild($supplier_id) | out-null
# Abschließend INVENTORIES Knoten mit in den Root-Knoten einhängen
$xml.DocumentElement.AppendChild($inventories) | out-null
# Ausgabepfad erstellen
$outpath = join-path $file.DirectoryName ($file.Basename + ".xml")
# XML Dokument im Ausgabepfad speichern
$xml.Save($outpath)
}
Ich würde dir auch mal ans Herz legen dich in die Grundlagen von XML Dokumenten einzuarbeiten dann verstehst du das mit den Namespaces auch besser. Auch wenn die Materie trocken anmutet, du wirst sehen sie hilft dir jedes mal wenn du mit XML-Dateien hantieren musst. Und so viel gibt es da auch nicht zu verstehen.
https://www.data2type.de/xml-xslt-xslfo/xml/xml-in-a-nutshell/xml-grundl ...
Zusätzlich die Dokumentation zum XMLDocument-Object seinen Methoden und Eigenschaften auch ganz hilfreich für die Powershell da das die selben Objekte sind
https://docs.microsoft.com/de-de/dotnet/api/system.xml.xmldocument?view= ...
Hope this helps
Viel Erfolg.
Grüße Uwe
Zitat von @Springstil:
leider sind noch Fehler in der XML. So wie es aussieht auf der Stelle 1 in der ersten Zeile x‘239‘
Ich kann nicht ganz nachvollziehen was die damit meinen... Im Online Hex Editor
https://prnt.sc/11g6tpc
leider sind noch Fehler in der XML. So wie es aussieht auf der Stelle 1 in der ersten Zeile x‘239‘
Ich kann nicht ganz nachvollziehen was die damit meinen... Im Online Hex Editor
https://prnt.sc/11g6tpc
Bitte in Zukunft keine externen Bilder Links mehr! Du kannst Bilder hier im Forum hochladen, siehe Links ganz unten das Bildchen.
ist dieses Leerzeichen auch zu sehen. Nur wie kommt das bitte da rein? wenn ich es mit Notepad oder so öffne, ist es nicht zu sehen.
Das ist kein Leerzeichen das ist der reguläre Byte Order Mark EF BB BF Prefix einer UTF8 Datei, dieser ist vollkommen legitim.https://de.wikipedia.org/wiki/Byte_Order_Mark
G. Uwe
Zitat von @Springstil:
Der Fehlercode vom System vom Kunden lautet:
Error in line 1: XML file should begin with white spaces or <. (Found char :ï(Hex :239).
wenn ich mir den inhalt neu kopiere in eine Text Datei, habe ich im Hex Editor kein Byte Order Mark mehr drin. Kann ich das Problem irgendwie umgehen?
EDIT: Scheint daran zulegen das er nicht in UTF8 schreibt sondern in UTF8-BOM. Wie kann ich das denn beeinflussen???
Dann ist deren System wohl etwas unflexibel, indem Fall einfach die XML ohne BOM speichern Speicherprozdur in Zeile 76 austauschen durchDer Fehlercode vom System vom Kunden lautet:
Error in line 1: XML file should begin with white spaces or <. (Found char :ï(Hex :239).
wenn ich mir den inhalt neu kopiere in eine Text Datei, habe ich im Hex Editor kein Byte Order Mark mehr drin. Kann ich das Problem irgendwie umgehen?
EDIT: Scheint daran zulegen das er nicht in UTF8 schreibt sondern in UTF8-BOM. Wie kann ich das denn beeinflussen???
# XML Dokument im Ausgabepfad speichern
$writer = New-Object System.Xml.XmlTextWriter $outpath, (New-Object System.Text.UTF8Encoding $false)
$writer.Formatting = 'Indented'
$xml.Save($writer)
$writer.Close()
Servus nochmal.
Grüße Uwe
Zitat von @Springstil:
Hey ich habe ein Kleines Problem mit dem Skript. Verstehe aber nicht ganz wieso das passiert. Und zwar steht in der CSV die Zeit mit 01:36:28 drin. In der XML kommt dies aber ohne die Führende "0" raus. Sprich dort steht dann: 1:36:28
Kann ich hier im Test nicht nachvollziehen denn der Code ändert rein gar nichts an den Quelldaten, die wandern von der CSV so wies sie sind in die XML. Das wird bei dir zu 99% ein Anzeigefehler der XML-Datei sein.Hey ich habe ein Kleines Problem mit dem Skript. Verstehe aber nicht ganz wieso das passiert. Und zwar steht in der CSV die Zeit mit 01:36:28 drin. In der XML kommt dies aber ohne die Führende "0" raus. Sprich dort steht dann: 1:36:28
Wie kann ich also das Format ändern?
Wenn die Daten aber unterschiedlich z,B, (ohne führende Nullen) vorliegen kannst du sie in folgender Zeile so vereinheitlichen$time.innerText = ([timespan]$_.time).ToString('t')