ElementTree XML Problem

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
madthomas
User
Beiträge: 35
Registriert: Dienstag 7. August 2007, 10:32
Wohnort: WND
Kontaktdaten:

ElementTree XML Problem

Beitragvon madthomas » Mittwoch 9. Juli 2008, 12:55

Hallo
ich hab die Aufgabe bekommen mittels einens Parser bestimmt Textteile auszulesen . Der Tag sieht etwas so aus

<Message code="" severity="" time="">
<UserType name="irgendwas" profile="Profile1"
script="blablablubb"></UserType>
<Agent>Superman</Agent>
<Text>Fehler drin
</Text>
<Time>26.06.2008 13:19:41</Time>
</Message>

den Agenten den Fehler und die Zeit mit Datum

hab jetzt mal ein skript von hier modifiziert aber irgendwie findet der nicht.

Code: Alles auswählen

import re
from BeautifulSoup import BeautifulStoneSoup
xml = open("detailedReport.xml")

soup = BeautifulStoneSoup(xml)
print "Beginn"
for text in soup("Message"):
   attrs = dict(text.attrs)
   print "tag     :", text
   print "string  :", text.string
   print "content :", "".join([str(item) for item in text.contents])
   print "contents:", text.contents
   print "Text    :", attrs.get("Text")
   print "Time    :", attrs.get("Time")
   print "Agent   :", attrs.get("Agent")
   print
   
print "Ende"
Zuletzt geändert von madthomas am Freitag 11. Juli 2008, 10:00, insgesamt 1-mal geändert.
BlackJack

Beitragvon BlackJack » Mittwoch 9. Juli 2008, 14:59

`BeautifulStoneSoup` ist nicht gerade das ideale Werkzeug um XML zu parsen. Das Modul ist für kaputtes (X)HTML gedacht. Bei "echtem" XML sollte man aber erwarten können, das es auch wohlgeformt ist und die entsprechenden XML-Werkzeuge verwenden.

Problem ist, das HTML bei Tags keinen Unterschied zwischen Gross- und Kleinschschreibung macht und `BeautifulSoup` deshalb alle Tags in klein Geschriebene umwandelt. Deshalb wird bei ``soup('Message')`` nichts gefunden.

Ein ``print soup`` hätte das sehr schnell aufgedeckt.
madthomas
User
Beiträge: 35
Registriert: Dienstag 7. August 2007, 10:32
Wohnort: WND
Kontaktdaten:

Beitragvon madthomas » Donnerstag 10. Juli 2008, 07:03

was wäre den ein besseres Werkzeug?
so er kann mir was auslesen nur leider klappt das ganze nicht so richtig.
Wie lese ich was ziwschen den Tags aus?
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Beitragvon Zap » Donnerstag 10. Juli 2008, 07:13

Ich würde ElementTree verwendent.

Ab Python 2.5 in der Standardbibliothek. (gibts aber auch für die älteren Versionen)

Code: Alles auswählen

In [17]: from xml.etree import ElementTree as ET

In [18]: tree = ET.fromstring("""<Message code="" severity="" time="">
   ....: <UserType name="irgendwas" profile="Profile1"
   ....: script="blablablubb"></UserType>
   ....: <Agent>Superman</Agent>
   ....: <Text>Fehler drin
   ....: </Text>
   ....: <Time>26.06.2008 13:19:41</Time>
   ....: </Message>""")

In [19]: agent = tree.find("Agent")

In [20]: agent.text
Out[20]: 'Superman'
madthomas
User
Beiträge: 35
Registriert: Dienstag 7. August 2007, 10:32
Wohnort: WND
Kontaktdaten:

Beitragvon madthomas » Donnerstag 10. Juli 2008, 09:27

ok hab auch gelesen das ElementTree eine besser Lösung ist.
ich hab jetzt noch folgendes Problem
Mein Code sieht mittleweile so aus und ist in einer Datei
[code=]
<BaselineReport>
<Message code="" severity="" time="">
<UserType name="irgendwas" profile="Profile1"
script="blablablubb"></UserType>
<Agent>Superman</Agent>
<Text>Fehler drin
</Text>
<Time>26.06.2008 13:19:41</Time>
</Message>
<Message code="" severity="" time="">
<UserType name="irgendwas" profile="Profile1"
script="blablablubb"></UserType>
<Agent>Superman</Agent>
<Text>Fehler drin
</Text>
<Time>26.06.2008 13:19:41</Time>
</Message>
</BaselineReport>
[/code]

Habs jetzt mal so versucht aber es klappt nicht

Code: Alles auswählen

from xml.etree import ElementTree as et

files = file("detailedReport.xml", "r")
etree = et.parse(files)
files.close()
root_tag = etree.getroot()
files_tag = root_tag.find("BaselineReport")
if files_tag:
    for file_tag in files_tag.findall("Message"):
        print file_tag.get("Agent")
        print "  " + (file_tag.text or "")


edit:
so hab jetzt mal weiter probiert und raus bekommen das der BaselineReport nicht findet und deswegen erst garnicht den if teil ausführt
Zuletzt geändert von madthomas am Donnerstag 10. Juli 2008, 09:39, insgesamt 1-mal geändert.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Beitragvon Zap » Donnerstag 10. Juli 2008, 09:37

Du must in deiner Hirarchie erstmal noch eine Ebene Tiefer gehen und die Message Blöcke auswählen.

Code: Alles auswählen

from xml.etree import ElementTree as et

files = file("detailedReport.xml", "r")
etree = et.parse(files)
files.close()
root_tag = etree.getroot()
for message in root_tag.findall("Message"):
    print message.find("Agent").text
madthomas
User
Beiträge: 35
Registriert: Dienstag 7. August 2007, 10:32
Wohnort: WND
Kontaktdaten:

Beitragvon madthomas » Donnerstag 10. Juli 2008, 09:51

Zap hat geschrieben:Du must in deiner Hirarchie erstmal noch eine Ebene Tiefer gehen und die Message Blöcke auswählen.

Code: Alles auswählen

from xml.etree import ElementTree as et

files = file("detailedReport.xml", "r")
etree = et.parse(files)
files.close()
root_tag = etree.getroot()
for message in root_tag.findall("Message"):
    print message.find("Agent").text


das funktiert irgendwie nicht der findet Message nicht
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Beitragvon Zap » Donnerstag 10. Juli 2008, 11:47

madthomas hat geschrieben:Mein Code sieht mittleweile so aus und ist in einer Datei
[code=]
<BaselineReport>
<Message code="" severity="" time="">
<UserType name="irgendwas" profile="Profile1"
script="blablablubb"></UserType>
<Agent>Superman</Agent>
<Text>Fehler drin
</Text>
<Time>26.06.2008 13:19:41</Time>
</Message>
<Message code="" severity="" time="">
<UserType name="irgendwas" profile="Profile1"
script="blablablubb"></UserType>
<Agent>Superman</Agent>
<Text>Fehler drin
</Text>
<Time>26.06.2008 13:19:41</Time>
</Message>
</BaselineReport>
[/code]


Mit der Beispieldatei sieht das Ergebnis bei mir so aus:

Code: Alles auswählen

Der Inhalt deiner XML Datei sieht (laut deinem Beispiel) so aus:



In [35]: cpaste
Pasting code; enter '--' alone on the line to stop.
:from xml.etree import ElementTree as et
:
:files = file("detailedReport.xml", "r")
:etree = et.parse(files)
:files.close()
:root_tag = etree.getroot()
:for message in root_tag.findall("Message"):
:    print message.find("Agent").text
:--
Superman
Superman
madthomas
User
Beiträge: 35
Registriert: Dienstag 7. August 2007, 10:32
Wohnort: WND
Kontaktdaten:

Beitragvon madthomas » Donnerstag 10. Juli 2008, 12:18

Sorry aber hab noch einen fehler bei mir übersehen deswegen klappt das auch nicht ich muss noch eine Ebene tiefer
[code=]
<BaselinReport>
<MessageList>(deswegen hat das auch nicht geklappt)
<Message>
<Agent>
</Agent>
</Message>
</MessageList>
</BaselineReport>
[/code]

Code: Alles auswählen

for messagelist in root_tag.findall("MessageList"):
    for message in messagelist.findall("Message"):
        print message.find("Agent").text


habs jetzt so und es klappt bis zu diesem Punkt
madthomas
User
Beiträge: 35
Registriert: Dienstag 7. August 2007, 10:32
Wohnort: WND
Kontaktdaten:

Beitragvon madthomas » Donnerstag 10. Juli 2008, 13:58

So soweit läuft mein Script. Leider befindet sich bei einem Text ein Umlaut und beim schreiben in die Datei bringt er einen Fehler
[code=]
ile "XMLparser.py", line 14, in <module>
print ("%s;%s" % (time,text))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 65: ordinal not in range(128)
[/code]

Code: Alles auswählen

# -*- coding: iso-8859-1 -*-
import sys
from xml.etree import ElementTree as et
files = file("detailedReport.xml", "r")
etree = et.parse(files)
files.close()
out_file = open("test.csv", "w")
root_tag = etree.getroot()
for messagelist in root_tag.findall("MessageList"):
    for message in messagelist.findall("Message"):
        time = message.find("Time").text
        text =  message.find("Text").text
   text = text.strip()
        print ("%s;%s" % (time,text))
   out_file.write("%s;%s" % (time, text))#habs hier auch mal mit encode('utf-8') versucht aber er findet im ersten satz kein umlaut und bricht dann ab
   out_file.write("\n")
out_file.close()

Wie kann ich das am besten lösen
BlackJack

Beitragvon BlackJack » Donnerstag 10. Juli 2008, 17:17

Wenn `unicode`-Objekte das Programm verlassen, sei es durch ``print`` oder schreiben in eine Datei, müssen sie in Bytes umgewandelt werden, also "gewöhnliche" `str`-Objekte. Bei ``print`` kann man Glück haben, dass Python heraus finden konnte, was zum Beispiel die Standardausgabe für eine Kodierung erwartet, aber spätestens bei Dateien kann man das nicht mehr automatisch ermitteln und Du musst explizit die `encode()`-Methode mit einer passenden Kodierung verwenden. Oder die Datei mit `codecs.open()` öffnen.
madthomas
User
Beiträge: 35
Registriert: Dienstag 7. August 2007, 10:32
Wohnort: WND
Kontaktdaten:

Beitragvon madthomas » Freitag 11. Juli 2008, 09:58

ich hab es mal so versucht

Code: Alles auswählen

import codecs
from xml.etree import ElementTree as et
files = file("detailedReport.xml", "r")
etree = et.parse(files)
files.close()
out_file = codecs.open("test.csv", "w", "utf-16") #codecs.open
root_tag = etree.getroot()
for messagelist in root_tag.findall("MessageList"):
    for message in messagelist.findall("Message"):
        time = message.find("Time").text
        text =  message.find("Text").text
   text = text.strip()
        print ("%s;%s" % (time,text))
   out_file.write("%s;%s" % (time, text))
   out_file.write("\n")
out_file.close()

weil mir das am einfachsten erschien aber es klappt nicht
BlackJack

Beitragvon BlackJack » Freitag 11. Juli 2008, 10:09

Definiere "klappt nicht". Ich sehe da auf den ersten Blick schonmal einen bösen Einrückungsfehler. Und natürlich kann Dir das ``print`` noch Probleme machen, wenn der Interpreter nicht erraten kann, was das Programm am anderen Ende von `sys.stdout` für eine Kodierung erwartet.
madthomas
User
Beiträge: 35
Registriert: Dienstag 7. August 2007, 10:32
Wohnort: WND
Kontaktdaten:

Beitragvon madthomas » Freitag 11. Juli 2008, 10:52

Sorry
meinte damit das der Fehler immer noch der Selbe ist.
[code=]
26.06.2008 13:43:59;Error(blablablubb)
26.06.2008 13:47:58;Error(blablablubb)
Traceback (most recent call last):
File "XMLparser.py", line 13, in <module>
print ("%s;%s" % (time,text))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 65: ordinal not in range(128)
>Exit code: 1
[/code]
und in der Zeile die da kommt ist ein Umlaut
madthomas
User
Beiträge: 35
Registriert: Dienstag 7. August 2007, 10:32
Wohnort: WND
Kontaktdaten:

Beitragvon madthomas » Freitag 11. Juli 2008, 13:47

Ok es lag wirklich am print.
Jetzt hab ich nur noch ein Problem. Immer wenn ich in die Dateischreiben will macht der keine neue Zeile habs mit verschiedenen Lösungen schon versucht.

Code: Alles auswählen

import codecs
from xml.etree import ElementTree as et
files = file("detailedReport.xml", "r")
etree = et.parse(files)
files.close()
out_file = codecs.open("test.csv", "w", "utf-8")
root_tag = etree.getroot()
for messagelist in root_tag.findall("MessageList"):
    for message in messagelist.findall("Message"):
        time = message.find("Time").text
        text =  message.find("Text").text
        agent = message.find("Agent").text
        text = text.strip()
        time = time.replace(" ",";")
        out_file.write("%s;%s;1" % (time, text)+"\n")
        out_file.write("%s;%s;1" % (time, agent)+'\n')
        out_file.write('\n')
        out_file.write("\n")
        out_file.write("%s;%s;1" % (agent, text))
out_file.close()

Wie bekomme ich das hin das ich am Ende von out_file.write eine neue Zeile schreiben kann
Keins der \n tut seinen Dienst

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder