PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Daten aus CSV Datei verarbeiten



tobi.b.
14.11.23, 14:11
Hallo Community,

derzeit stehe ich vor einem kleinen Problem und benötige einen Denkanstoß.

Ich habe eine CSV-Datei die ich in eine XML Datei umwandeln möchte, soweit ist das kein Problem, aber es gibt in der CSV Zellen die mehrere Zeilen beinhalten.

Hier ein einfaches Beispiel:

1;3;444;493;"Das ist
die Zelle
die ich meine"
2;5;423;409;ffff
3;5;453;455;ffuh

wenn ich jetzt die CSV Datei Zeile für Zeile bearbeite, dann führt das natürlich zu einem Fehler, da die zweite Zeile in dem Beispiel als neuer Datensatz verstanden wird.
Hättet ihr einen Tipp für mich wie ich damit umgehen kann?

System: Debian 10 (VM)
Code bisher in Linux Bash

Gruß Tobi

ThorstenHirsch
14.11.23, 20:39
Das ist keine gültige CSV-Datei, gib sie dem Excel-Akrobat zurück. :D
Ernsthaft: ich würde zuerst alle Zeilenumbrüche per Suchen&Ersetzen ändern, z.B. in ein Leerzeichen oder ein Zeichen, das in der Datei nicht vorkommt. Dann kannst du sie normal verarbeiten und immer noch entscheiden, was du mit dem Zeichen machst.

Huhn Hur Tu
15.11.23, 06:20
Zuerst mal klug*******en CSV heisst "Comma Seperated .." du hast also ein SSV so viel zur Klug*******erei.
Als zweites, empfehle demjenigen, welcher die Daten erzeugt hat, je nach OS, unter windows, mal und Laufwerk c:/ das VCerzeichniss "system32" mit den 32Bit Resten zu loeschen, bzw. unter Linux "/etc/apparmor*" dann klappt das auch mit den Daten. Sorry den konnte ich mir gerade nicht verkneifen.


Eine Moeglichkeit ist


deine Datenonjekte mit einen distintectn Zeichen zu umfassen, heisst alles was darin ist, ist ein Objekt was zu XML werden kann, evtl. ueber den Umweg Json.


cat Datafile | grep "[0-9]" | sed 's/^/@@/g'
head -n1 | sed 's/^@//g'
tail -n1 | sed 's/^@//g'


also alles was zwischen einem Paar @@ liegt ist ein Objekt



@1;3;444;493;"Das ist
die Zelle
die ich meine"
@@2;5;423;409;ffff
@@3;5;453;455;ffuh@


zum verarbeiten, aber ich empfehle die Loesung mit dem loeschen von system32 ;)

nopes
15.11.23, 09:43
Du könntest außerdem Umschalten, so in die Richtung, wenn nach einem S Wert ( ; ) ein " folgt, wird der Block erst dann geschlossen, wenn du wieder ein " findest.
Alternativ statt aller Zeilenumbrüche würde ich nur die nehmen, die "doof" sind - s/^([^"]+"[^"\n]+)\n/$1/g; das muss aber wiederholt werden, bis es keine Treffer mehr gibt

Naja schön ist das alles nicht

marce
15.11.23, 13:45
An all jene, die sagen "dat geht mal gar nicht": https://www.rfc-editor.org/rfc/rfc4180, 2.6:

6. Fields containing line breaks (CRLF), double quotes, and commas
should be enclosed in double-quotes. For example:

"aaa","b CRLF
bb","ccc" CRLF
zzz,yyy,xxx

erste Frage: einmalig oder wiederholend?

Falls einmalig: Date in Libreoffice reinladen und als XML exportieren.
Falls mehrmals: Es gibt nette Libs, Converter-Tools, die einem den Stress abnehmen.

tobi.b.
16.11.23, 09:12
An all jene, die sagen "dat geht mal gar nicht": https://www.rfc-editor.org/rfc/rfc4180, 2.6:


erste Frage: einmalig oder wiederholend?

Falls einmalig: Date in Libreoffice reinladen und als XML exportieren.
Falls mehrmals: Es gibt nette Libs, Converter-Tools, die einem den Stress abnehmen.

Danke für eure Antworten.

Für den genaueren Hintergrund noch ein paar Informationen.
Wir haben ca. 1000-1500 Textbausteine die mit Leerzeichen und Zeilenumbrüchen formatiert sind und diese Formatierung beibehalten werden müsste (daher bringt es mir nichts die Zeilenumbrüche zu entfernen).
Diese Daten stehen aktuell in einer CSV-Datei (wie in meinem Beispiel vereinfacht dargestellt) und müssen im XML-Format in das Zielsystem importiert werden.
Wenn das klappen sollte, wären noch 3 weitere CSV-Dateien vorhanden, mit der gleichen Größe, die umgewandelt werden müssten.

die Daten müssten dann in eine XML Format umgewandelt werden, was wie gesagt kein Problem ist bis auf die Zeilen mit Umbrüchen.
Bei XML sind die Umbrüche kein Problem, diese lassen sich dann einfach in das Zielsystem importieren Beispiel:

<Tabelle1>
<Format>1</Format>
<tests>Name</tests>
<test>bla</test>
</tests>
<Description>AT2-Beschreibung</Description>
<Body>langertext der mehr als eine Zeile betrifft
Bla bala
bla bla
blaaaaaaaa</Body>
</Tabelle1>

Bei den Convertern hatte ich bis jetzt das Problem, dass eingerückte Bereiche wie in dem oberen Beispiel <tests> nicht berücksichtig wurden da ich es in der csv nicht darstellen konnte und daher nur eine Ebene verarbeitet wurden (hoffe das ist verständlich ausgedrückt).

@Nopes

Du könntest außerdem Umschalten, so in die Richtung, wenn nach einem S Wert ( ; ) ein " folgt, wird der Block erst dann geschlossen, wenn du wieder ein " findest.

Sowas hatte ich gesucht, aber nicht gefunden, hättest du ein Beispiel für mich?

@Huhn Hur Tu das teste ich mal danke!

marce
16.11.23, 16:25
Du könntest außerdem Umschalten, so in die Richtung, wenn nach einem S Wert ( ; ) ein " folgt, wird der Block erst dann geschlossen, wenn du wieder ein " findest.
wird nicht klappen, da in den :"[...]"-Bereichen ja wiederum escapte " vorkommen können.

@TE: woher sollen denn die
<tests>Name</tests>
<test>bla</test>
</tests>-Bereiche kommen? Ich seh' die in der CSV nicht.

Ich würde trotzdem weiter mit den default-Convertern arbeiten - die gibt's in jeder bel. Sprache und perl z.B. oder php, go, python sollte bei heutigen Disitris ja problemlos installierbar sein oder schon installiert sein.

Ggf. könnte man sich auch noch sowas wie Jinja-Templating anschauen.

nopes
16.11.23, 20:10
Wenn du schon XML Schreibst, würde ich mir das ganze Escaping dafür sparen und die Blöcke in eine CDATA Section schreiben. Das mit dem Umschalten des Trennzeichens würde ich etwa so lösen - sa https://onlinegdb.com/PgxLe-YMR

def to_xml_string(csv_string):
'''little helper to convert a csv string into a xml string'''
blockNo=0
blockContent = ''
escaped = False
delimeter = ';'
print(' <entry>')
for char in csv_string:
if char == '\\':
escaped = True
continue
elif char == '"' and delimeter == ';':
delimeter = '"'
continue

if escaped:
blockContent = blockContent + '\\' + char
escaped = False
continue

if char == delimeter:
blockNo = blockNo + 1;
print(' <block><![CDATA[{}]]></block>'.format(blockContent.strip('\n')))
blockContent = ''
if delimeter == '"':
delimeter = ';'
else:
blockContent = blockContent + char


if blockNo == 5:
print(' </entry>')
n = 0

print(' <block><![CDATA[{}]]></block>'.format(blockContent.strip('\n')))
print(' </entry>')



#
# main
#
data1='1;3;444;493;"Das ist\ndie Zelle\ndie ich meine"\n2;5;423;409;ffff\n' # some test data from a string
data2=''
with open('data.csv', 'r') as f: # some test data from a file
data2 = f.read()

print('<?xml version="1.0" encoding="UTF-8">')
print('<root>')
to_xml_string(data1)
to_xml_string(data2)
print('</root>')



Erzeugt diese Ausgabe:
<?xml version="1.0" encoding="UTF-8">
<root>
<entry>
<block><![CDATA[1]]></block>
<block><![CDATA[3]]></block>
<block><![CDATA[444]]></block>
<block><![CDATA[493]]></block>
<block><![CDATA[Das ist
die Zelle
die ich meine]]></block>
</entry>
</entry>
</entry>
<block><![CDATA[2]]></block>
<block><![CDATA[5]]></block>
<block><![CDATA[423]]></block>
<block><![CDATA[409]]></block>
<block><![CDATA[ffff]]></block>
</entry>
<entry>
<block><![CDATA[4]]></block>
<block><![CDATA[7]]></block>
<block><![CDATA[777]]></block>
<block><![CDATA[4242]]></block>
<block><![CDATA[Das ist
die Zelle
die ich meine - aus einer Datei mit \"Sonderzeichen\"]]></block>
</entry>
</entry>
</entry>
<block><![CDATA[5]]></block>
<block><![CDATA[6]]></block>
<block><![CDATA[423]]></block>
<block><![CDATA[409]]></block>
<block><![CDATA[ffff]]></block>
</entry>
</root>


[edit]Ein kleinen Fehler steckt drin, den musst du ggf selber finden und beheben

marce
17.11.23, 11:38
" wird in csv nicht mit \ sondern mit " escaped. :-)

tobi.b.
27.11.23, 09:24
Danke für eure Hilfe, das Problem konnte ich mit dem Onlineconverter: https://www.convertcsv.com/csv-to-xml.htm beheben.
Die Scriptvorschläge habe ich getestet, aber ich bin ehrlich gesagt nicht ganz dahinter gekommen wie es funktioniert.
Aber sobald ich mehr Zeit habe, werde ich mich dem Thema nochmal widmen!