XML auslesen und als CSV ausgeben

PlatinStandard

Cadet 4th Year
Registriert
Okt. 2011
Beiträge
84
Guten Tag!
Ich hab eine XML Datei die mit einem PDF Paser erstellt wurde.

Hier ein Auszug aus der XML Datei.

<?xml version="1.0" encoding="UTF-8"?>
<PDF>
<DocumentInfo>
<Author>XXXXX</Author>
<Creator>Form YMR_PRINT_ERS EN</Creator>
<Producer>SAP NetWeaver 750 </Producer>
<CreationDate>2018-01-18T11:40:03Z</CreationDate>
</DocumentInfo>
<FormData />
<Pages quantity="17">
<Page nr="1" height="842.0" width="595.0" rotation="0">
<Fonts>
<Font name="C001" type="Font" baseFont="Courier" />
<Font name="C002" type="Font" baseFont="Courier-Bold" />
<Font name="C003" type="Font" baseFont="CourierNew" />
<Font name="C004" type="Font" baseFont="Helvetica-Bold" />
<Font name="C005" type="Font" baseFont="Helvetica" />
</Fonts>
<Images />
<TextLines>
<LineData font="C002" size="10" xpos="50" ypos="698">Seller:</LineData>
<LineData font="C002" size="14" xpos="310" ypos="698">Invoice Self-billing Original</LineData>
<LineData font="C001" size="12" xpos="50" ypos="686">my company</LineData>
<LineData font="C005" size="12" xpos="468" ypos="679">Page: 1 / 17 </LineData>
<LineData font="C001" size="12" xpos="50" ypos="674">xxxxx</LineData>
<LineData font="C003" size="12" xpos="50" ypos="674">C</LineData>
<LineData font="C001" size="12" xpos="50" ypos="674">xxxxx</LineData>
<LineData font="C005" size="8" xpos="310" ypos="674">Document no. / Date </LineData>
<LineData font="C005" size="8" xpos="468" ypos="674">Currency</LineData>
<LineData font="C001" size="12" xpos="50" ypos="662">xxxxx</LineData>
<LineData font="C001" size="10" xpos="310" ypos="662">xxxx / xxxx</LineData>
<LineData font="C001" size="10" xpos="468" ypos="662">EUR</LineData>
<LineData font="C001" size="12" xpos="50" ypos="650">xxx</LineData>
<LineData font="C005" size="8" xpos="310" ypos="650">FI document no. / Date</LineData>
<LineData font="C001" size="10" xpos="310" ypos="638">xxxx/ xxx</LineData>
<LineData font="C005" size="8" xpos="310" ypos="626">Your vendor number in our co. </LineData>
<LineData font="C005" size="8" xpos="468" ypos="626">Your tax ID number</LineData>
<LineData font="C002" size="10" xpos="50" ypos="614">Buyer:</LineData>
<LineData font="C001" size="10" xpos="310" ypos="614">xxxx</LineData>
<LineData font="C001" size="10" xpos="468" ypos="614">xxxxx</LineData>
<LineData font="C001" size="12" xpos="50" ypos="602">xxxxx</LineData>
<LineData font="C005" size="8" xpos="310" ypos="602">Our customer no. in your co. </LineData>
<LineData font="C005" size="8" xpos="468" ypos="602">Our tax ID number</LineData>
<LineData font="C001" size="12" xpos="50" ypos="590">xxx</LineData>
<LineData font="C001" size="10" xpos="468" ypos="590">xxx</LineData>
<LineData font="C001" size="12" xpos="50" ypos="578">1xxx</LineData>
<LineData font="C005" size="8" xpos="310" ypos="578">Vendor invoice number</LineData>
<LineData font="C001" size="10" xpos="310" ypos="566">xxx</LineData>
<LineData font="C005" size="8" xpos="310" ypos="554">Processed by </LineData>
<LineData font="C005" size="8" xpos="468" ypos="554">Your tax number</LineData>
<LineData font="C001" size="10" xpos="310" ypos="542">Ms. xxxx </LineData>
<LineData font="C001" size="10" xpos="468" ypos="542">xxxx</LineData>
<LineData font="C005" size="8" xpos="310" ypos="530">Telephone no.</LineData>
<LineData font="C005" size="8" xpos="361" ypos="530"> / Fax no. </LineData>
<LineData font="C001" size="10" xpos="310" ypos="518">xxxxx</LineData>
<LineData font="C005" size="8" xpos="310" ypos="506">Delivery date: See attachment</LineData>
<LineData font="C001" size="10" xpos="310" ypos="494">07.01.2018</LineData>
<LineData font="C005" size="8" xpos="310" ypos="482">E-mail address</LineData>
<LineData font="C001" size="10" xpos="310" ypos="470">xxx@xxxx.com</LineData>
<LineData font="C001" size="12" xpos="50" ypos="426">As agreed, we have settled the following goods and :services and</LineData>
<LineData font="C001" size="12" xpos="50" ypos="416">credited the amounts to your account in our company::</LineData>
<LineData font="C001" size="12" xpos="50" ypos="406">___________________________________________________:____________________</LineData>
<LineData font="C002" size="12" xpos="50" ypos="385">Item</LineData>
<LineData font="C002" size="12" xpos="94" ypos="385">Material</LineData>
<LineData font="C002" size="12" xpos="266" ypos="385">Description</LineData>
<LineData font="C001" size="12" xpos="94" ypos="372">Shipment</LineData>
<LineData font="C001" size="12" xpos="94" ypos="359">Purchase Order</LineData>
<LineData font="C001" size="12" xpos="94" ypos="346">SEnt line </LineData>
<LineData font="C001" size="12" xpos="230" ypos="346">Service text</LineData>
<LineData font="C001" size="12" xpos="94" ypos="334">INT. SERVICE NO. </LineData>
<LineData font="C001" size="12" xpos="230" ypos="334">EXT. SERVICE NO.</LineData>
<LineData font="C001" size="12" xpos="94" ypos="322">QTY </LineData>
<LineData font="C001" size="12" xpos="230" ypos="322">UN</LineData>
<LineData font="C001" size="12" xpos="432" ypos="322">NET VALUE IN EUR</LineData>
<LineData font="C002" size="12" xpos="94" ypos="310">Qty</LineData>
<LineData font="C002" size="12" xpos="230" ypos="310">Un</LineData>
<LineData font="C002" size="12" xpos="338" ypos="310">TaxC</LineData>
<LineData font="C002" size="12" xpos="432" ypos="310">Net value in EUR</LineData>
<LineData font="C002" size="12" xpos="230" ypos="298">Price/UoM</LineData>
<LineData font="C002" size="12" xpos="338" ypos="298">VAT amount</LineData>
<LineData font="C002" size="12" xpos="439" ypos="298">Gross value EUR</LineData>
<LineData font="C001" size="12" xpos="50" ypos="287">___________________________________________________:____________________</LineData>
<LineData font="C002" size="12" xpos="50" ypos="263">00001</LineData>
<LineData font="C002" size="12" xpos="94" ypos="263">Freight charges (see enclosed)</LineData>
<LineData font="C001" size="12" xpos="94" ypos="248">0070492</LineData>
<LineData font="C001" size="12" xpos="216" ypos="248">/ 22.12.2017</LineData>
<LineData font="C001" size="12" xpos="94" ypos="236">7000370</LineData>
<LineData font="C001" size="12" xpos="216" ypos="236">/ 00001</LineData>
<LineData font="C002" size="12" xpos="72" ypos="224"> 1</LineData>
<LineData font="C002" size="12" xpos="230" ypos="224">AU</LineData>
<LineData font="C002" size="12" xpos="432" ypos="224"> 525,00</LineData>
<LineData font="C002" size="12" xpos="230" ypos="212">525,00</LineData>
<LineData font="C002" size="12" xpos="346" ypos="212">0,00</LineData>
<LineData font="C002" size="12" xpos="504" ypos="212">525,00</LineData>
<LineData font="C002" size="12" xpos="50" ypos="185">00002</LineData>
<LineData font="C002" size="12" xpos="94" ypos="185">Freight charges (see enclosed)</LineData>
<LineData font="C001" size="12" xpos="94" ypos="170">0070492</LineData>
<LineData font="C001" size="12" xpos="216" ypos="170">/ 02.01.2018</LineData>
<LineData font="C001" size="12" xpos="94" ypos="158">7000370</LineData>
<LineData font="C001" size="12" xpos="216" ypos="158">/ 00001</LineData>
<LineData font="C002" size="12" xpos="72" ypos="146"> 1</LineData>
<LineData font="C002" size="12" xpos="230" ypos="146">AU</LineData>
<LineData font="C002" size="12" xpos="432" ypos="146"> 670,00</LineData>
<LineData font="C002" size="12" xpos="230" ypos="134">670,00</LineData>
<LineData font="C002" size="12" xpos="346" ypos="134">0,00</LineData>
<LineData font="C002" size="12" xpos="504" ypos="134">670,00</LineData>
<LineData font="C004" size="8" xpos="50" ypos="79">Kunde GMBH</LineData>

Nun soll aus dieser XML Datei eine CSV Datei generiert werden.
Es soll nach dem Text: "Freight charges (see enclosed)" gesucht werden und der Inhalt aus den nächsten elf Zeilen genommen werden und diese dann nebeneinander in eine CSV Datei geschirben werden.
Wird der Text "Freight charges (see enclosed)" nochmal gefunden, soll eine neue Zeile in der CSV Datei begeonnen werden.

Wenn der Text "Total" gefunden wird, soll nicht weiter im XML Dokument gesucht werden.

Hat jemand eine Idee, wie ich dies Umsetzen kann?
 
Ich bezweifle, dass das ohne weiteres mit Office machbar ist. Zumindest ist mir kein normales Office Programm bekannt, das XML lesen kann.

Wenn du allerdings ein paar Zeilen programmieren kannst, ist das mit Java oder Python in wenigen Minuten gemacht.
 
Alle Office-Programme können XML-Dateien lesen. Warum auch nicht? Der Rest ist nicht so einfach machbar, aber öffnen funktioniert.
 
Wenn du so willst, dann kann auch das NotePad und WordPad XML lesen. Und ja, die aktuellen Word und Excel Dateien sind intern auch nur XML. Aber das hilft hier vorne und hinten nicht weiter ;)
 
Vielleicht hlfts beim Basteln:

Mir ist auch eine XML auf den Tisch gekommen die ich »normalisieren« wollte; einfach nur alle Einrückungen raus und ganz besonders das eine LF am Zeilenende in typisches CR+LF umwandeln (kurz gesagt, als TXT ablegen um nicht im Original rumzubasteln).

Excel - Office 2016 - (aus anderen Gründen) macht mit seinem VBA Bauchlandungen. Einlesen per INPUT geht nicht, LINE INPUT lädt die ganze Datei in die INPUT-Variable (was auch nicht wirklich pricklend ist) und beim Binary GET hat es sich weggehängt.

Mag sein, dass du da doch noch was sinnvolles mit erreichst. Die gelesenen Zeilen (zwischen den LF) nach Stichworten zu filtern und n-Mal Zeilen zu lesen ist dann kein Programmierhexenwerk mehr.
Ich überlege gerade ob der eingelesene Super-String nach dem Schema wie GET zu zerlegen wäre..?

CN8
 
Das kann man schon mit VBA machen. XML Datei per Knopfdruck in Excel einlesen und in einem neuen CSV File ablegen.

Fuer 50 EUR bau ich dir das...schoen als Excel AddIn mit eigenem Symbol im Ribbon (Vorausgesetzt du benutzt eine aktuelle version von Excel und KEIN Mac)

Schick mir einfach ne PM ;-)
 
Der TE hat doch gar nicht gefragt, ob das in Excel umsetzbar ist. Die Aufgabenstellung hier ist, bestimmte Daten aus XML-Dateien in CSV zu schreiben. Und das ist prinzipiell sehr einfach machbar mit einer XSLT Transformation.
 
Also es handelt sich hierbei um einen Prozess in einem Unternehmen der Folgendermassen aussieht.
Wir bekommen eine PDF Datei (eine Gutschrift vom Kunden) diese wird automatisch aus dem E-Mail Postfach gerippt. Wir haben Lobster Data, der die PDF Datei in XML Umwandelt, dann soll eine CSV Datei automatisch erstellt werden, die wiederrum von unserer ERP Software eingelesen werden kann.
Also ich suche einen Prozess, der möglichst die Aufgabenstellung automatisiert durchführt. Zu WingX: Die Thematik mit XSLT Transformation ist mir neu. Ich muss mich da erst einlesen.... Ich möchte mich auch gerne an die anderen für Ihre Vorschläge bedanken.
 
Das geht auch relativ einfach mittels einer Batch-Datei ...
Code:
@ECHO OFF
setlocal enableDelayedExpansion
:: Dateien fuer Eingabe und Ausgabe setzen
set xmlFile=input.xml
set csvFile=output.csv
set startString="Freight charges (see enclosed)"
set endString="Total"
set /A counter=0

:: Datei zeilenweise durchlaufen, Trennzeichen < und >
:: ausgewertet wird der zweite Teilstring
for /f "delims=<> tokens=2" %%a in (%xmlFile%) do (
  if !counter! == 0 (
    :: Start gefunden?
    if "%%a" == %startString% (
      :: counter auf 1 setzen
      set counter=1
    )
    :: Ende gefunden?
    if "%%a" == %endString% (
      :: Batchdatei beenden
      goto :EOF
    )
  ) else (
    if !counter! LSS 12 (
      if !counter! == 1 (
        :: erste Spalte
        set csvLine="%%a"
      ) else (
        :: neue Spalte
        set csvLine=!csvLine!,"%%a"
      )
      set /A counter=!counter!+1
      if !counter! == 12 (
        :: Zeile ist vollständig, ausgeben und counter auf 0 setzen
        echo !csvLine! >> %csvFile%
        set counter=0
      )		
    )
  )
)
 
Zuletzt bearbeitet: (Werte für Ausgabe in "" gesetzt wegen Komma)
Hallo Andreas,
ich habe deinen Text genommen, die Pfade zur XML und CSV Angepasst und als xml zu csv.bat abgespeichert.
Beim Ausführen Startet nur kurz das DOS Fenster und schließt sich wieder. Die CSV wird jedoch nicht erstellt.
Habe noch an Ende ein PAUSE eingebaut, aber dann steht im DOS Fenster einfach nur "Weiter mit beliebiger Taste..."
Aber ich denke dein löschungsansetz geht schon in die richtige Richtung.
 
Wenn die Pfade Leerzeichen enthalten, dann müssen sie in "" gesetzt werden. Ansonsten ist es mit den Beispieldaten aus dem ersten Posting getestet. Ergebnis ist dabei:
0070492,/ 22.12.2017,7000370,/ 00001, 1,AU, 525,00,525,00,0,00,525,00,00002
0070492,/ 02.01.2018,7000370,/ 00001, 1,AU, 670,00,670,00,0,00,670,00,Kunde GMBH
Eventuell sollte man ein anderes Trennzeichen nehmen, da das Komma auch in den Daten vorkommt

Mit der Änderung vom vorigen Posting:
"0070492","/ 22.12.2017","7000370","/ 00001"," 1","AU"," 525,00","525,00","0,00","525,00","00002"
"0070492","/ 02.01.2018","7000370","/ 00001"," 1","AU"," 670,00","670,00","0,00","670,00","Kunde GMBH"
 
Zuletzt bearbeitet:
Ich habe jetzt die Dateien direkt auf "E:" gelegt, sowohl die Datei als auch die Batch.
Ich habe das Trennzeichen auf ";" gesetzt, weil auch Kommas in den Daten vorkommen.
Auch habe ich das ECHO OFF auf ECHO ON gestellt und wie schon geschrieben ein Pause am Ende gesetzt.
Es öffnete sich ein CMD Fenster und es das wurde angezeigt:
if !counter! == 12 (
echo !csvLine! 1>>E:output.csv
set counter=0
)
) ) )

E:\>(if !counter! == 0 (if "LineData font="C005" size="6" xpos="50" ypos="31"" == "Freight charges (see enclosed)" (set counter=1 ) ) else (if !counter! LSS 11 (
if !counter! == 1 (set csvLine=LineData font="C005" size="6" xpos="50" ypos="31" ) else (set csvLine=!csvLine!;LineData font="C005" size="6" xpos="50" ypos="31" )
set /A counter=!counter!+1
if !counter! == 12 (
echo !csvLine! 1>>E:output.csv
set counter=0
)
) ) )

E:\>(if !counter! == 0 (if "LineData font="C005" size="8" xpos="304" ypos="31"" == "Freight charges (see enclosed)" (set counter=1 ) ) else (if !counter! LSS 11 (
if !counter! == 1 (set csvLine=LineData font="C005" size="8" xpos="304" ypos="31" ) else (set csvLine=!csvLine!;LineData font="C005" size="8" xpos="304" ypos="31" )
set /A counter=!counter!+1
if !counter! == 12 (
echo !csvLine! 1>>E:output.csv
set counter=0
)
) ) )

E:\>(if !counter! == 0 (if "LineData font="C005" size="8" xpos="50" ypos="24"" == "Freight charges (see enclosed)" (set counter=1 ) ) else (if !counter! LSS 11 (
if !counter! == 1 (set csvLine=LineData font="C005" size="8" xpos="50" ypos="24" ) else (set csvLine=!csvLine!;LineData font="C005" size="8" xpos="50" ypos="24" )
set /A counter=!counter!+1
if !counter! == 12 (
echo !csvLine! 1>>E:output.csv
set counter=0
)
) ) )

E:\>(if !counter! == 0 (if "/TextLines" == "Freight charges (see enclosed)" (set counter=1 ) ) else (if !counter! LSS 11 (
if !counter! == 1 (set csvLine=/TextLines ) else (set csvLine=!csvLine!;/TextLines )
set /A counter=!counter!+1
if !counter! == 12 (
echo !csvLine! 1>>E:output.csv
set counter=0
)
) ) )

E:\>(if !counter! == 0 (if "/Page" == "Freight charges (see enclosed)" (set counter=1 ) ) else (if !counter! LSS 11 (
if !counter! == 1 (set csvLine=/Page ) else (set csvLine=!csvLine!;/Page )
set /A counter=!counter!+1
if !counter! == 12 (
echo !csvLine! 1>>E:output.csv
set counter=0
)
) ) )

usw... viel viel mehr zeilen....
 
Dann weicht die XML-Datei von den hier im Thread geposteten Daten ab. Anscheinend sind in jeder Zeile noch Zeichen vor dem ersten "<" (Leerzeichen oder Tabulator, vermutlich durch die Forensoftware entfernt). Deswegen ist es nicht der 2. sondern erst der 3. Teilstring.
Darum musst Du
Code:
for /f "delims=<> tokens=2" %%a in (%xmlFile%) do (
ändern in
Code:
for /f "delims=<> tokens=3" %%a in (%xmlFile%) do (
 
Zuletzt bearbeitet:
Das ist sehr cool...wieder was neues gelernt, kann man bestimmt mal gebrauchen. Die < und > als Delimiter zu verwenden ist schon eine geniale Idee. Danke Andreas :D
 
Das XSL Stylesheet dafür würde so aussehen (ganz schnell hingeklatscht, geht bestimmt auch schöner):
Code:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" encoding="UTF-8" />
    <xsl:template match="/">
        <xsl:for-each select="/PDF/Pages/Page/TextLines/LineData[contains(.,'Freight charges (see enclosed)')]|/PDF/Pages/Page/TextLines/LineData[contains(.,'Item')]">
            <xsl:value-of select="./following-sibling::LineData[1]" />
            <xsl:text>;</xsl:text>
            <xsl:value-of select="./following-sibling::LineData[2]" />
            <xsl:text>;</xsl:text>
            <xsl:value-of select="./following-sibling::LineData[3]" />
            <xsl:text>;</xsl:text>
            <xsl:value-of select="./following-sibling::LineData[4]" />
            <xsl:text>;</xsl:text>
            <xsl:value-of select="./following-sibling::LineData[5]" />
            <xsl:text>;</xsl:text>
            <xsl:value-of select="./following-sibling::LineData[6]" />
            <xsl:text>;</xsl:text>
            <xsl:value-of select="./following-sibling::LineData[7]" />
            <xsl:text>;</xsl:text>
            <xsl:value-of select="./following-sibling::LineData[8]" />
            <xsl:text>;</xsl:text>
            <xsl:value-of select="./following-sibling::LineData[9]" />
            <xsl:text>;</xsl:text>
            <xsl:value-of select="./following-sibling::LineData[10]" />
            <xsl:text>;</xsl:text>
            <xsl:value-of select="./following-sibling::LineData[11]" />
            <xsl:text>&#xD;</xsl:text>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Und das Ergebnis nach einer XSLT Transformation:
Code:
Material;Description;Shipment;Purchase Order;SEnt line ;Service text;INT. SERVICE NO. ;EXT. SERVICE NO.;QTY ;UN;NET VALUE IN EUR
0070492;/ 22.12.2017;7000370;/ 00001; 1;AU; 525,00;525,00;0,00;525,00;00002
0070492;/ 02.01.2018;7000370;/ 00001; 1;AU; 670,00;670,00;0,00;670,00;Kunde GMBH
 
Es gibt XSLT und XQUERY Programme, der bekannteste ist wohl SAXON. Es gibt aber auch eine Implementation von Microsoft, msxml.exe, die ich verwendet habe. Dem Programm füttert man eine XML-Datei, das dazugehörige Stylesheet und die gewünschte Ausgabedatei, es versucht dann anhand des Styesheet die Ausgabe zu befüllen. Mit XSLT kann man verschiedene Ausgaben erreichen, entweder wieder XMl oder eben CSV/Plaintext oder HTML.
 
Zurück
Oben