Inhalte aus einem Open-Office ODS extrahieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Dr_Enquinox
User
Beiträge: 5
Registriert: Samstag 1. November 2008, 10:01

Guten Tag,
ich versuche seit einiger Zeit mithilfe von XML Informationen aus einer Open-Office-Tabelle zu extrahieren. Dazu muss ich die Tabelle Zeilenweise parsen und den Inhalt jeder Zeile in eine eigene Liste füllen. WIe das genau aussehen soll, ist jedoch eher unerheblich.
Das Problem ist folgendes: Ich habe ein vorgefertigtes XML-Parserscript aus dem Netz gefischt, dieses Script ignoriert nun leider doppelte Werte in einer Zeile. Wenn also zwei Zellen nebeneinander denselben Wert haben, werden einfach alle Dopplungen ausgelassen.

Hier ist das Script:

Code: Alles auswählen

#!/usr/bin/env python
 
# import the needed modules
import zipfile
import xml.parsers.expat
 
# get content xml data from OpenDocument file
ziparchive = zipfile.ZipFile("laufwerke.ods", "r")
xmldata = ziparchive.read("content.xml")
ziparchive.close()
 
class Element(list):
	def __init__(self, name, attrs):
		self.name = name
		self.attrs = attrs
 
class TreeBuilder:
	def __init__(self):
		self.root = Element("root", None)
		self.path = [self.root]
	def start_element(self, name, attrs):
		element = Element(name, attrs)
		self.path[-1].append(element)
		self.path.append(element)
	def end_element(self, name):
		assert name == self.path[-1].name
		self.path.pop()
	def char_data(self, data):
		self.path[-1].append(data)
 
# create parser and parsehandler
parser = xml.parsers.expat.ParserCreate()
treebuilder = TreeBuilder()
# assign the handler functions
parser.StartElementHandler  = treebuilder.start_element
parser.EndElementHandler    = treebuilder.end_element
parser.CharacterDataHandler = treebuilder.char_data
 
# parse the data
parser.Parse(xmldata, True)

def showtree(node, prefix=""):
	#print prefix, node.name
	if node.name == "table:table-row":
		print "Neue Zeile:"
	for e in node:
		if isinstance(e, Element):
			showtree(e, prefix + "  ")
		else:
			print e
 
showtree(treebuilder.root)
Hier ist ein Screen der ODS

[img=http://img526.imageshack.us/img526/9940 ... do0.th.png]

Hier ist die Ausgabe des Scripts für die ersten Zwei Zeilen:
Neue Zeile:
ID
Name
CPU
Grafikkarte
Mainboard
Ram
HDD
Kuehler
Netzteil
Laufwerk
Preis
NB-LW
Cardreader
Floppy
Lightscripe
DVD - s
DVD - l
HD-DVD
Blue-Ray - s
Blue-Ray - l
Watt
kuehler S A
kuehler S 478
kuehler S 939
kuehler S 940
kuehler S 754
kuehler S 775
kuehler S AM2
kuehler S AM2+
zoll
Kapazität
speed
zugriffszeit
cache
NCQ
sockel anz
sockel
Takt
L1 Cache
L2 Cache
L3 Cache
FSB/HT
EE
Virtualisierung
MMX
SSE
CnQ
NX-Bit
3dNow!
Bit
Cores
Gewaehrleistung
Garantie
Marke
luefter strom
ATX
Micro ATX
Firewire
Sound
Lan
Lan geschw
USB typ
USB
SATA
IDE
DDR
DDR2
Chipsatz
PCI
PCIx1
PCIx16
DirectX
Kuehler sockel
gb-ram
Grakaname
Kuehler
Kuehler sockel
sockel
sockel anz
CPU
Netzteil
Ram
HDD
luefter strom
ATX
micro ATX
graka
USB
Firewire
eSATA
SATA
IDE
LAN
USB
Neue Zeile:
261010071
LG GSA-T20N Dual-DVD-+R
NULL
1
54,99
1
NULL
1
NULL
NULL
1
NULL
Wie man sieht, müsste die Ausgabe für die zweite Zeile länger sein, weil wesentlich mehr NULL-Werte hintereinander stehen. Woran könnte das liegen?

Mit freundlichen Grüßen,
Karl Kröber aka Dr_Enquinox
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hallo Dr_Enquinox, willkommen im Forum,

Wenn du das Openoffice-Dokument irgendwo hochlädst, dann könnte ich es mir vielleicht mal ansehen, sofern ich etwas Zeit finde.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Dr_Enquinox
User
Beiträge: 5
Registriert: Samstag 1. November 2008, 10:01

Danke für die schnelle Antwort, Leonidas.

Hier ist das ODS: http://rapidshare.de/files/40808438/laufwerke.ods.html

Mit freundlichen Grüßen,
Karl Kröber aka Dr_Enquinox
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dr_Enquinox hat geschrieben:Hier ist das ODS: http://rapidshare.de/files/40808438/laufwerke.ods.html
Hast du keinen besseren Provider? Rapidshare ist mit diesen Capchas und dem Auslaufen der Dateien so ziemlich die schlechteste Möglichkeit.

Edit: Ein Ansatz wäre es, ElementTree zu verwenden. Sieht dann so aus.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Dr_Enquinox
User
Beiträge: 5
Registriert: Samstag 1. November 2008, 10:01

Ok, hier bitte:

http://www.djuniversum.de/mountaindju/doc/laufwerke.ods

Ich habe es mit deinem Pastebin probiert und auch hier tritt dasselbe Problem auf. Multiple Werte werden zu einem gemacht. Komischer Fehler, ich kenne mich mit XML allerdings auch nicht genug aus um irgendwelche Vermutungen anzustellen. Diese Übersetzung in Python-Listen ist nur die Vorbereitung für den eigentlichen Algorithmus. Danke für deine Hilfe soweit, Leonidas.

Mit freundlichen Grüßen,
Karl Kröber aka Dr_Enquinox
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Das liegt dann aber daran, dass diese Daten so in der ``content.xml`` schlichtweg nicht stehen. In diesem Fall wäre es eher einfacher es vor dem verarbeiten in CSV zu konvertieren.

Kannst dir ja mal die content.xml im Browser ansehen, die zeigen eine Baumstruktur an.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Dr_Enquinox
User
Beiträge: 5
Registriert: Samstag 1. November 2008, 10:01

Ok, danke für den Tip.

Mit freundlichen Grüßen,
Karl Kröber aka. Dr_Enquinox
Dr_Enquinox
User
Beiträge: 5
Registriert: Samstag 1. November 2008, 10:01

Auf den Tip mit dem .cvs hin, habe ich das Problem gelöst. Speichere die Datei als CVS und parse sie zeilenweise wie jede andere Textdatei auch. Vielen Dank Leonidas.

Mit freundlichen Grüßen,
Karl
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dr_Enquinox hat geschrieben:Auf den Tip mit dem .cvs hin, habe ich das Problem gelöst. Speichere die Datei als CVS und parse sie zeilenweise wie jede andere Textdatei auch.
Python bringt bereits in der Stdlib einen CVS-Parser mit...
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten