chrisen
Goto Top

XML Datei per Skript ändern

Hallo zusammen,
ich habe eine Frage zur automatischen Konvertierung einer XML Datei.

Und zwar:
Wir bekommen aus unserem Warenwirtschaftssystem folgende XML Datei raus:


<?xml version="1.0" standalone="yes"?>  
<DocumentElement>
  <article>
    <ordernumber>100002</ordernumber>
    <mainnumber>100002</mainnumber>
    <name>Artikelname</name>
    <tax>19.00</tax>
    <suppliername>Hersteller</suppliername>
    <Price>0.000000</Price>
  </article>
  <article>
    <ordernumber>100005</ordernumber>
    <mainnumber>100005</mainnumber>
    <name>Artikelname</name>
    <tax>19.00</tax>
    <suppliername>Hersteller</suppliername>
    <Price>0.000000</Price>
  </article>
</DocumentElement>

Das Problem ist, dass wir für den Import in ein anderes Programm ein anderes Format benötigen:
Am Beispiel hier der Preis und Artikel.
Leider ist es nicht möglich dies direkt aus dem Warenwirtschaftssystem zu ändern.

<Root>
   <articles>
     <article>
	  <orderNumber> 100005 </orderNumber>
	  <mainNumber> 100005 </mainNumber>
	  <name>Münsterländer Aperitif 16%</name>
	  <supplierName>Feinbrennerei Sasse</supplierName>
	  <tax>19.00</tax>
	  <price>
		  <price>14.95</price>
	  </price>
      </article>
   </articles>
</Root>

Gibt es eine Möglichkeit diese Änderungen per Skript durchzuführen? Bzw. gibt es für so etwas ein Programm?
Das heißt: Automatisch (zum Beispiel) alle 5 Std. die XML Datei aus einem bestimmten Ordner holen, bearbeiten und wieder in einen bestimmten Ordner speichern.

Würde mich riesig über Antworten freuen!

Grüße,
chrisen

Content-Key: 313935

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

Ausgedruckt am: 19.03.2024 um 02:03 Uhr

Mitglied: 129813
Lösung 129813 30.08.2016 um 10:30:44 Uhr
Goto Top
Hi
you only need to transfrom it with XSLT
http://www.w3schools.com/xsl/xsl_intro.asp

Regards
Mitglied: colinardo
Lösung colinardo 30.08.2016 aktualisiert um 12:21:04 Uhr
Goto Top
Hallo chrisen,
das ist kein Problem. Wie @129813 schreibt ist für sowas XSLT normalerweise das Mittel der Wahl, geht zwar auch per Skript aber schneller ist's mit XSLT.

Dazu erstellt du eine Datei mit folgendem Inhalt und gibst Ihr den Namen transform.xslt
<?xml version="1.0" encoding="UTF-8"?>  
<xsl:stylesheet version="1.0"  
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />  
<xsl:template match="/">  
  <root>
  <articles>
    <xsl:for-each select="DocumentElement/article">  
      <article>
	  <orderNumber><xsl:value-of select="ordernumber"/></orderNumber>  
	  <mainNumber><xsl:value-of select="mainnumber"/></mainNumber>  
	  <name><xsl:value-of select="name"/></name>  
	  <supplierName><xsl:value-of select="suppliername"/></supplierName>  
	  <tax><xsl:value-of select="tax"/></tax>  
	  <price>
		<price><xsl:value-of select="Price"/></price>  
	  </price>
      </article>
    </xsl:for-each>
    </articles>
  </root>
</xsl:template>
</xsl:stylesheet>
ACHTUNG: XSLT und XML ist casesensitive !!

Dann erstellst du dir ein Powershell-Skript mit folgendem Inhalt, die Pfade musst du natürlich anpassen.
function Transform-XML{
    param([string]$xsltfile,[string]$xmlfile,[string]$xmlfileout
    )
try{
        $xslt = New-Object system.xml.xsl.xslcompiledtransform
        $xslt.Load($xsltfile)
        $xslt.Transform($xmlfile,$xmlfileout)
    }catch{
        throw $_.Exception.Message
   }
}
Transform-XML -xsltfile 'C:\transform.xslt' -xmlfile 'C:\input.xml' -xmlfileout 'A:\output.xml'  
Skript ausführen, fertig.


XSL Transformation kann man fast mit jeder beliebigen Skriptsprache umsetzen. Das war jetzt ein Powershell Beispiel.

Hier als Ergänzung noch die VBS/VBA Variante für das XSL Stylesheet von oben, für diejenigen für die Powershell noch immer ein böhmisches Dorf sein sollte face-wink
Const XMLIN = "C:\input.xml"  
Const XMLOUT = "C:\output.xml"  
Const XSLT = "C:\transform.xslt"  
Set xmlDoc = CreateObject("Msxml2.DOMDocument.6.0")  
Set xsltDoc = CreateObject("Msxml2.DOMDocument.6.0")  
xsltDoc.async = False : xmlDoc.async = False
xmlDoc.load(XMLIN) : xsltDoc.load(XSLT)
xmlDoc.transformNodeToObject xsltDoc,xmlDoc
xmlDoc.save XMLOUT
msgbox "XML Datei wurde transformiert und liegt unter: " & XMLOUT, vbInformation  

Grüße Uwe

Falls der Beitrag gefällt, seid so nett und unterstützt mich durch eine kleine Spende / If you like my contribution please support me and donate
Mitglied: chrisen
chrisen 30.08.2016 um 11:37:31 Uhr
Goto Top
Super vielen vielen Dank!!

Es ist echt einfacher als ich gedacht hätte.

Grüße,
chrisen
Mitglied: colinardo
colinardo 30.08.2016 aktualisiert um 12:21:34 Uhr
Goto Top
Keine Ursache. Schöne Woche. face-smile

Grüße Uwe
Mitglied: chrisen
chrisen 30.08.2016 um 14:03:00 Uhr
Goto Top
Hallo collinardo,
ich habe leider noch ein kleines Problem/Frage, wenn ich das Skript ausführe:
Ich bekomme als Output Datei immer eine Datei heraus die wie folgt aussieht:

<?xml version="1.0" encoding="UTF-8"?> 
<root>
	<articles></articles>
</root>
Mitglied: colinardo
colinardo 30.08.2016 aktualisiert um 14:09:55 Uhr
Goto Top
Hast du auf Groß-Kleinschreibung im XSL-Stylesheet geachtet? Die XPath-Selectoren wie in folgender Zeile sind case sensitive, d.h. diese müssen exakt mit der Quelle übereinstimmen sonst bekommst du so solch eine Ausgabe wie bei dir
<xsl:for-each select="DocumentElement/article"> 
Ich habe mich exakt an dein obiges Quelldokument gehalten, und damit funktioniert das hier einwandfrei. Du wirst dort einfach einen kleinen Typo gemacht haben oder dein Quelldokument ist nicht gleich formatiert wie du es hier gepostet hast. Eventuell hast du aber auch das XSLT nicht im UTF8 Format gespeichert.

Grüße Uwe
Mitglied: chrisen
chrisen 30.08.2016 um 14:15:16 Uhr
Goto Top
Ja ich habe mich exakt an die Groß- und Kleinschreibung gehalten.

Meine Input Datei sieht zum Test so aus:

<?xml version="1.0" encoding="UTF-8"?>  
<DocumentElement>
  <article>
    <ordernumber>100002</ordernumber>
    <mainnumber>100002</mainnumber>
    <name>Artikelname</name>
    <tax>19.00</tax>
    <suppliername>Hersteller</suppliername>
    <Price>0.000000</Price>
  </article>
  <article>
    <ordernumber>100005</ordernumber>
    <mainnumber>100005</mainnumber>
    <name>Artikelname</name>
    <tax>19.00</tax>
    <suppliername>Hersteller</suppliername>
    <Price>0.000000</Price>
  </article>
</DocumentElement>

die XSL so:

<?xml version="1.0" encoding="UTF-8"?>  
<xsl:stylesheet version="1.0"  
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />  
<xsl:template match="/">  
  <root>
  <articles>
    <xsl:for-each select="DocumentElement/article">  
      <article>
	  <orderNumber><xsl:value-of select="ordernumber"/></orderNumber>  
	  <mainNumber><xsl:value-of select="mainnumber"/></mainNumber>  
	  <name><xsl:value-of select="name"/></name>  
	  <supplierName><xsl:value-of select="suppliername"/></supplierName>  
	  <tax><xsl:value-of select="tax"/></tax>  
	  <price>
		<price><xsl:value-of select="Price"/></price>  
	  </price>
      </article>
    </xsl:for-each>
    </articles>
  </root>
</xsl:template>
</xsl:stylesheet>
Mitglied: colinardo
colinardo 30.08.2016 aktualisiert um 14:23:50 Uhr
Goto Top
Kann ich nicht bestätigen, läuft fehlerfrei:
Ergebnis des Transforms:
<?xml version="1.0" encoding="utf-8"?>  
<root>
  <articles>
    <article>
      <orderNumber>100002</orderNumber>
      <mainNumber>100002</mainNumber>
      <name>Artikelname</name>
      <supplierName>Hersteller</supplierName>
      <tax>19.00</tax>
      <price>
        <price>0.000000</price>
      </price>
    </article>
    <article>
      <orderNumber>100005</orderNumber>
      <mainNumber>100005</mainNumber>
      <name>Artikelname</name>
      <supplierName>Hersteller</supplierName>
      <tax>19.00</tax>
      <price>
        <price>0.000000</price>
      </price>
    </article>
  </articles>
</root>
Auf welchem OS und mit welcher PS Version machst du das ganze ?

Wurde hier auf Windows 7/10 mit PS4/5 problemlos getestet.
Mitglied: chrisen
chrisen 30.08.2016 aktualisiert um 14:29:29 Uhr
Goto Top
Ich mache das mit Windows 7 und mit der PS Version 2.0. Habe es zunächst zum testen mit einem VBScript (wie netterweise oben von dir beschrieben) gemacht
Mitglied: colinardo
colinardo 30.08.2016 aktualisiert um 14:35:01 Uhr
Goto Top
Hier funktionieren beide Versionen sowohl VBS als auch das PS in PS 2.0 Umgebung.

Ich tippe auf ein Encoding-Problem auf deiner Seite. Und überprüfe deine Skripte bitte nochmal, ich hatte sie nach dem Posten nachträglich oben noch etwas optimiert, vielleicht hattest du einfach eine falsche Version kopiert.
Mitglied: 129813
129813 30.08.2016 aktualisiert um 14:38:53 Uhr
Goto Top
I did a test and here it works too, both the VBS and PS4.0.

Regards
Mitglied: chrisen
chrisen 30.08.2016 um 14:43:01 Uhr
Goto Top
Oh man. Ich hatte einen ganz kleinen Fehler im Skript in der Namensgebung beim Input...

Vielen Dank nochmal für deine Hilfe!!!