bestimmte Daten aus XML auslesen und in liste speicher (sax)

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
PauleJS
User
Beiträge: 34
Registriert: Freitag 22. Oktober 2010, 14:58

hallo,

ich bin noch ein python anfänger und habe folgendes problem.

ich habe folgende xml datei
<rss>
<channel>
<title>title1</title>
<name> günther </name>
<marke> nike </marke>
</channel>
</rss>

ich möchte mit hilfe von sax nur den title und die marke auslesen. diese sollen dann in eine liste (wie ein assoziativer array aufgebaut) geschrieben werden

mein bisheriger code

Code: Alles auswählen

import xml.sax as sax

class DictHandler(sax.handler.ContentHandler):
	def __init__(self):	
		ergebnis = {}
		ergebnis[ "title"] = "";
		ergebnis[ "marke"] = "";
		print ergebnis

	def startElement (self, name, attrs):
		if name == 'item':
			
			ergebnis[ "title"] = attrs.get('title', "")  
	
	def characters (self):
		ergebnis[ "title"] = inhalt aus xml

	def load_file():
		handler = DictHandler()
		datei   = open("RSS.xml", "r")
		parser  = sax.make_parser()
		xml.sax.parse(datei, handler)
		datei.close()
		
DictHandler()
ich denke es geht hauptsächlich um die funktionen startElement und characters! Hier sollen die werte aus der xml in die liste übergeben werden.

bin für alle tipps und ratschläge offen

vielen dank im voraus für die mühe
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Nimm lieber lxml (ermöglich XPath) oder xml.etree.ElementTree mit den Modulen ist es viel einfacher und m.M.n. auch logischer XML-Datein auszulesen:

Code: Alles auswählen

from xml.etree import ElementTree as etree

xml = """<rss>
<channel>
<title>title1</title>
<name> günther </name>
<marke> nike </marke>
</channel>
</rss>"""

e = etree.fromstring(xml)
channel = e.find('channel')

for title, marke in zip(channel.iterfind('title'), channel.iterfind('marke')):
    print title.text, marke.text
Für Feeds gibts übrigens: http://www.feedparser.org/
the more they change the more they stay the same
PauleJS
User
Beiträge: 34
Registriert: Freitag 22. Oktober 2010, 14:58

Dav1d hat geschrieben:Nimm lieber lxml (ermöglich XPath) oder xml.etree.ElementTree mit den Modulen ist es viel einfacher und m.M.n. auch logischer XML-Datein auszulesen:

Code: Alles auswählen

from xml.etree import ElementTree as etree

xml = """<rss>
<channel>
<title>title1</title>
<name> günther </name>
<marke> nike </marke>
</channel>
</rss>"""

e = etree.fromstring(xml)
channel = e.find('channel')

for title, marke in zip(channel.iterfind('title'), channel.iterfind('marke')):
    print title.text, marke.text
Für Feeds gibts übrigens: http://www.feedparser.org/
ich habe deinen code nun folgermaßen verändert

Code: Alles auswählen

from xml.etree import ElementTree as etree

xml = open("RSS.xml", "r")

e = etree.fromstring(xml)
channel = e.find('channel')

for title, marke in zip(channel.iterfind('title'), channel.iterfind('brand')):
    print title.text, marke.text
bekomme aber jetzt folgende fehlermeldungen:
Traceback (most recent call last):
File "C:\Projects\Conversation\testForum.py", line 5, in <module>
e = etree.fromstring(xml)
File "C:\Python27\lib\xml\etree\ElementTree.py", line 1281, in XML
parser.feed(text)
File "C:\Python27\lib\xml\etree\ElementTree.py", line 1621, in feed
self._parser.Parse(data, 0)

ist es denn eigentlich sinnvoll dies alles direkt mit dem feedparser zu machen? es sind recht große feeds die eingelesen werden sollen!
Benutzeravatar
lutz.horn
User
Beiträge: 205
Registriert: Dienstag 8. November 2005, 12:57
Wohnort: Pforzheim

Wenn Du das XML aus einer Datei lesen möchtest, muss Du

Code: Alles auswählen

xml = open("RSS.xml", "r").read()
verwenden.
https://www.xing.com/go/invite/18513630.6a91d4
PauleJS
User
Beiträge: 34
Registriert: Freitag 22. Oktober 2010, 14:58

lutz.horn hat geschrieben:Wenn Du das XML aus einer Datei lesen möchtest, muss Du

Code: Alles auswählen

xml = open("RSS.xml", "r").read()
verwenden.
danke, aber dabei bekomme ich diese meldungen:

Traceback (most recent call last):
File "C:\Projects\Conversation\testForum.py", line 5, in <module>
e = etree.fromstring(xml)
File "C:\Python27\lib\xml\etree\ElementTree.py", line 1281, in XML
parser.feed(text)
File "C:\Python27\lib\xml\etree\ElementTree.py", line 1623, in feed
self._raiseerror(v)
File "C:\Python27\lib\xml\etree\ElementTree.py", line 1487, in _raiseerror
raise err
xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 9, column 175
BlackJack

@PauleJS: Du hast beim ersten mal zwar einen Teil des Tracebacks angegeben aber nicht welche Ausnahme ganz unten eigentlich steht.

Vergiss den Lösungsvorschlag von lutz.horn, der ist Mist. Wenn Du eine Datei parsen möchtest, nimm die `etree.parse()`-Funktion.
PauleJS
User
Beiträge: 34
Registriert: Freitag 22. Oktober 2010, 14:58

BlackJack hat geschrieben:@PauleJS: Du hast beim ersten mal zwar einen Teil des Tracebacks angegeben aber nicht welche Ausnahme ganz unten eigentlich steht.

Vergiss den Lösungsvorschlag von lutz.horn, der ist Mist. Wenn Du eine Datei parsen möchtest, nimm die `etree.parse()`-Funktion.
DANKE!

ich bekomme jetzt auch eine ausgabe, aber die gesamte xml wird mir nun angezeigt und ich möchte ja nur bestimmte informationen (title, brand, link, price) aus der xml auslesen

ausserdem bekomme ich trotzdem noch folgende fehlermeldung:

File "C:\Projects\Conversation\testForum.py", line 5, in <module>
e = etree.parse(xml)
File "C:\Python27\lib\xml\etree\ElementTree.py", line 1176, in parse
tree.parse(source, parser)
File "C:\Python27\lib\xml\etree\ElementTree.py", line 646, in parse
source = open(source, "rb")
IOError: [Errno 2] No such file or directory: '<rss xmlns:g-custom="http://base.google.com/cns/1.0" xmlns:g-core="http://base.google.com/ns/1.0" version="2.0">\n <channel>\n <title> .... die gesamte xml wird hier weiter angezeigt

ausserdem handelt es sich im moment ja auch nichtmehr um sax! ist sax also hierfür nicht der beste weg?
BlackJack

@PauleJS: Jetzt schau doch mal in die Dokumentation was `parse()` als Argument erwartet und was Du stattdessen übergibst.
PauleJS
User
Beiträge: 34
Registriert: Freitag 22. Oktober 2010, 14:58

BlackJack hat geschrieben:@PauleJS: Jetzt schau doch mal in die Dokumentation was `parse()` als Argument erwartet und was Du stattdessen übergibst.
ich habe das so verstanden!

Code: Alles auswählen

xml = open("testRSS.xml", "r").read()

e = etree.parse(xml)
BlackJack

@PauleJS: Das hast Du falsch verstanden. So missverständlich ist *die Dokumentation* für `xml.etree.ElementTree.parse()` doch eigentlich nicht!?
PauleJS
User
Beiträge: 34
Registriert: Freitag 22. Oktober 2010, 14:58

BlackJack hat geschrieben:@PauleJS: Das hast Du falsch verstanden. So missverständlich ist *die Dokumentation* für `xml.etree.ElementTree.parse()` doch eigentlich nicht!?
die definition lautet:
xml.etree.ElementTree.parse(source, parser=None)
Parses an XML section into an element tree. source is a filename or file object containing XML data. parser is an optional parser instance. If not given, the standard XMLTreeBuilder parser is used. Returns an ElementTree instance.

also kann ich doch bei source ganz einfach den dateinamen oder das objekt mit den daten angeben!
Gab
User
Beiträge: 21
Registriert: Montag 17. August 2009, 14:45

Es sollte reichen:

Code: Alles auswählen

import lxml.etree as lxml
xml = lxml.parse ("RSS.xml")
Die Felder auslesen erfolgt dann über Xpath:

Code: Alles auswählen

title = xml.xpath ("//title")[0].text
Grüße
gab
BlackJack

@PauleJS: Zeichenketten sind keine Dateiobjekte.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

PauleJS hat geschrieben:also kann ich doch bei source ganz einfach den dateinamen oder das objekt mit den daten angeben!
Ja, kannst du. Tust du aber nicht. Du übergibst eine Zeichenkette mit den XML-Daten.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

xml.etree.(c)ElementTree unterstützt kein Xpath, also funktioniert Gabs Lösung nur, wenn du lxml verwendest.

Für RSS/Atom-Feeds bietet sich allerdings das Feedparser Modul an.
the more they change the more they stay the same
Antworten