ElementTree und XML Fragen

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.
Benutzeravatar
MoR4euZ
User
Beiträge: 34
Registriert: Mittwoch 18. Oktober 2006, 21:21
Wohnort: Essen
Kontaktdaten:

ElementTree und XML Fragen

Beitragvon MoR4euZ » Sonntag 5. November 2006, 17:44

Guten Abend

Ich habe mich heute mal mit ElementTree beschäftigt.
Nach Stunden des ausprobierens und Tutorials lesen sind noch etliche Fragen in Bezug auf ElementTree und XML geblieben. :(

Ich habe folgende XML Datei:

Code: Alles auswählen

<?xml version="1.0" encoding="utf-8" ?>
<Processes>
    <Process id="1">
        <LongName>Calculator</LongName>
        <ShortName>calc</ShortName>
        <Launch>C:\WINDOWS\system32\calc.exe</Launch>
        <RunTime></RunTime>
    </Process>
    <Process id="2">
        <LongName>WordPad</LongName>
        <ShortName>rtf</ShortName>
        <Launch>C:\WINDOWS\system32\write.exe</Launch>
        <RunTime></RunTime>
    </Process>
    <Process id="3">
        <LongName>Solitaer</LongName>
        <ShortName>sol</ShortName>
        <Launch>C:\WINDOWS\system32\sol.exe</Launch>
        <RunTime></RunTime>
    </Process>
</Processes>


Daraus möchte ich alle LongName-Tags
und jedes Launch-Tag einzeln heraus ziehen.

Alle zusammen klapt schonmal:

Code: Alles auswählen

from xml.etree import ElementTree as etree

root = etree.parse('process.xml').getroot()
   
for element in root.findall('.///LongName'):
    print element.text
for element in root.getiterator('Launch'):
    print element.text


Code: Alles auswählen

Calculator
WordPad
Solitaer
C:\WINDOWS\system32\calc.exe
C:\WINDOWS\system32\write.exe
C:\WINDOWS\system32\sol.exe


Zu den Fragen:

Wie bekomme ich die Launch-Tags separat aus der XML Datei bei gleichem Tagnamen?

Wie kann ich die RunTime-Tags seperat schreiben?

Kann ich die id's in der XML Datei ansprechen?

Wie sieht es mit Umlauten in der XML Datei aus (bei Solitär)?

Muss man in der XML Datei mit TABs einrücken oder reicht da auch ein oder zwei SPACEs?

Wie bekomme ich mit python-Bordmitteln aus der XML Datei eine HTML Datei?


Ich hoffe die Fragen sind alle verständlich
Bin leicht verwirrt ;)
BlackJack

Re: ElementTree und XML Fragen

Beitragvon BlackJack » Sonntag 5. November 2006, 19:51

MoR4euZ hat geschrieben:Daraus möchte ich alle LongName-Tags
und jedes Launch-Tag einzeln heraus ziehen.

Alle zusammen klapt schonmal:

Code: Alles auswählen

from xml.etree import ElementTree as etree

root = etree.parse('process.xml').getroot()
   
for element in root.findall('.///LongName'):
    print element.text
for element in root.getiterator('Launch'):
    print element.text


Hier ziehst Du doch die einzelnen Elemente einzeln heraus!? Ich versteh die Frage nicht so ganz.

Kann ich die id's in der XML Datei ansprechen?


Am einfachsten wahrscheinlich indem Du den Baum mit `XMLID()` erzeugst. Die Funktion gibt neben dem Baum auch gleich ein Dictionary mit IDs zurück:

Code: Alles auswählen

In [63]: print a
<?xml version="1.0" encoding="utf-8" ?>
<Processes>
   <Process id="1">
       <LongName>Calculator</LongName>
       <ShortName>calc</ShortName>
       <Launch>C:\WINDOWS\system32\calc.exe</Launch>
       <RunTime></RunTime>
   </Process>
   <Process id="2">
       <LongName>WordPad</LongName>
       <ShortName>rtf</ShortName>
       <Launch>C:\WINDOWS\system32\write.exe</Launch>
       <RunTime></RunTime>
   </Process>
   <Process id="3">
       <LongName>Solitär</LongName>
       <ShortName>sol</ShortName>
       <Launch>C:\WINDOWS\system32\sol.exe</Launch>
       <RunTime></RunTime>
   </Process>
</Processes>


In [64]: doc, ids = etree.XMLID(a)

In [65]: ids
Out[65]:
{'1': <Element Process at -486fdc74>,
 '2': <Element Process at -486fd9d4>,
 '3': <Element Process at -486fd814>}


Wie sieht es mit Umlauten in der XML Datei aus (bei Solitär)?


Das Textattribut enthält ein Unicode-Objekt falls der Textknoten etwas ausserhalb von ASCII enthält:

Code: Alles auswählen

In [76]: ids['3'].getchildren()[0].text
Out[76]: u'Solit\xe4r'


Muss man in der XML Datei mit TABs einrücken oder reicht da auch ein oder zwei SPACEs?


Das kannst Du machen wie Du willst. Überall wo kein Text erwartet wird, kannst Du so viel oder wenig "whitespace" einfügen wie du magst.

Wie bekomme ich mit python-Bordmitteln aus der XML Datei eine HTML Datei?


Das ist ziemlich vage. Wie soll das denn in HTML aussehen?
Benutzeravatar
MoR4euZ
User
Beiträge: 34
Registriert: Mittwoch 18. Oktober 2006, 21:21
Wohnort: Essen
Kontaktdaten:

Beitragvon MoR4euZ » Montag 6. November 2006, 23:04

danke für deine antwort blackjack
es war sehr hilfreich
danach habe ich gesucht :)

Code: Alles auswählen

from xml.etree import ElementTree as etree

source = """\
<?xml version="1.0" encoding="utf-8" ?>
<Processes>
    <Process id="1">
        <LongName>Calculator</LongName>
        <ShortName>calc</ShortName>
        <Launch>C:\WINDOWS\system32\calc.exe</Launch>
        <RunTime></RunTime>
    </Process>
    <Process id="2">
        <LongName>WordPad</LongName>
        <ShortName>rtf</ShortName>
        <Launch>C:\WINDOWS\system32\write.exe</Launch>
        <RunTime></RunTime>
    </Process>
    <Process id="3">
        <LongName>Solitaer</LongName>
        <ShortName>sol</ShortName>
        <Launch>C:\WINDOWS\system32\sol.exe</Launch>
        <RunTime></RunTime>
    </Process>
</Processes>"""

doc, ids = etree.XMLID(source)

path = ids['1'].getchildren()[2].text

print path


wie kann ich nun meine externe xml datei wieder einbinden?

bei "source = etree.parse('process.xml','r')" bekomme ich folgenden traceback

Code: Alles auswählen

Traceback (most recent call last):
  File "pyfire6.py", line 7, in <module>
    source = etree.parse('process.xml','r')
  File "C:\Python25\lib\xml\etree\ElementTree.py", line 862, in parse
    tree.parse(source, parser)
  File "C:\Python25\lib\xml\etree\ElementTree.py", line 586, in parse
    parser.feed(data)
AttributeError: 'str' object has no attribute 'feed'


wie muss ich die xml datei nun einbinden?
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Dienstag 7. November 2006, 10:45

parse(source, parser=None) [#]

Parses an XML document into an element tree.

source
A filename or file object containing XML data.
parser
An optional parser instance. If not given, the standard XMLTreeBuilder parser is used.
Returns:
An ElementTree instance

Du willst etree.parse('dateiname.xml') ohne zweiten Parameter. Oder etree.ElementTree(file='dateiname.xml').
Benutzeravatar
MoR4euZ
User
Beiträge: 34
Registriert: Mittwoch 18. Oktober 2006, 21:21
Wohnort: Essen
Kontaktdaten:

Beitragvon MoR4euZ » Dienstag 7. November 2006, 16:03

hmm funktioniert alles nicht :(
liegt sicher an der xmlid fuktion die ich nicht so ganz verstehe ;)
BlackJack

Beitragvon BlackJack » Dienstag 7. November 2006, 20:31

Die Funktion möchte eine Zeichenkette haben. Du musst einfach die XML Datei komplett lesen und das Ergebnis an die Funktion übergeben.
Benutzeravatar
MoR4euZ
User
Beiträge: 34
Registriert: Mittwoch 18. Oktober 2006, 21:21
Wohnort: Essen
Kontaktdaten:

Beitragvon MoR4euZ » Donnerstag 9. November 2006, 03:32

ok danke
das mit dem string habe ich hinbekommen :)

aber wie schreibe ich mit XMLID daten in die xmldatei?

http://codespeak.net/pipermail/lxml-che ... 00700.html

mehr brauchbares habe ich leider nicht gefunden
habe schon probiert es bei mir anzuwenden aber ohne erfolg bis jetzt

oder sollte ich mal lxml einrichten?
XMLID stammt ja woll von dort ab oder?
BlackJack

Beitragvon BlackJack » Donnerstag 9. November 2006, 09:34

MoR4euZ hat geschrieben:aber wie schreibe ich mit XMLID daten in die xmldatei?


Du bekommst ein ganz normales `Element`-Objekt und ein Dictionary zurück. Das `Element` kannst Du in einen `ElementTree` stecken und dann hast Du eine `write()`-Methode.

Code: Alles auswählen

In [15]: a = etree.XMLID('<test />')[0]

In [16]: b = etree.ElementTree(a)

In [17]: b.write(sys.stdout)
Benutzeravatar
MoR4euZ
User
Beiträge: 34
Registriert: Mittwoch 18. Oktober 2006, 21:21
Wohnort: Essen
Kontaktdaten:

Beitragvon MoR4euZ » Donnerstag 9. November 2006, 19:33

hmm sorry ich verstehe dein beispiel leider nicht irgentwie fehlen mir noch etliche basics dafür :/

hier mal ein komplettes beispiel (ohne eigene funktionen)

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import time
from decimal import Decimal as deci
from xml.etree import ElementTree as etree

#read path and old_runtime
f = file('process.xml', 'r')
s = f.read()
f.close()
doc, ids = etree.XMLID(s)
path = ids['1'].getchildren()[2].text
old_runtime = ids['1'].getchildren()[3].text
print 'alte RunTime: ', old_runtime

#runtime detectin
start_time = time.time()
os.system(path)
runtime = time.time() - start_time
print 'ermittelte RunTime: ', runtime

#runtime addition
new_runtime = deci(str(runtime)) + deci(old_runtime)
print 'neue RunTime: ', new_runtime

#write new_runtime
new_runtime = etree.XMLID('<RunTime />')[0]
b = etree.ElementTree(new_runtime)
b.write(sys.stdout)


Code: Alles auswählen

<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="Process.xsl"?>
<Process_db>
    <Process id="1">
        <LongName>Calculator</LongName>
        <ShortName>calc</ShortName>
        <Path>C:\WINDOWS\system32\calc.exe</Path>
        <RunTime>19.999999999</RunTime>
    </Process>
    <Process id="2">
        <LongName>WordPad</LongName>
        <ShortName>rtf</ShortName>
        <Path>C:\WINDOWS\system32\write.exe</Path>
        <RunTime></RunTime>
    </Process>
    <Process id="3">
        <LongName>Solitaer</LongName>
        <ShortName>sol</ShortName>
        <Path>C:\WINDOWS\system32\sol.exe</Path>
        <RunTime></RunTime>
    </Process>
</Process_db>


was fehlt oder passt nicht bei der write-methode?
habe etliche andere sachen probiert leider ohne erfolg
bei mir bleibt die xml-datei unverändert oder der inhalt wird ganz gelöscht/überschrieben
BlackJack

Beitragvon BlackJack » Donnerstag 9. November 2006, 22:28

MoR4euZ hat geschrieben:was fehlt oder passt nicht bei der write-methode?


Du erzeugst ein leeres RunTime-Element und speicherst das in der Datei `sys.stdout`, also die Ausgabe des Programms. Was erwartest Du denn?

Wenn Du das eingelesene XML-Dokument verändern willst, dann musst Du den Inhalt des eingelesenen RunTime-Elements verändern und den eingelesenen und nun veränderten Baum in eine Datei speichern.
Benutzeravatar
MoR4euZ
User
Beiträge: 34
Registriert: Mittwoch 18. Oktober 2006, 21:21
Wohnort: Essen
Kontaktdaten:

Beitragvon MoR4euZ » Freitag 10. November 2006, 00:35

BlackJack hat geschrieben:Wenn Du das eingelesene XML-Dokument verändern willst, dann musst Du den Inhalt des eingelesenen RunTime-Elements verändern und den eingelesenen und nun veränderten Baum in eine Datei speichern.


ok den satz verstehe ich :)
nur bekomme ich es nicht umgesetzt :roll:

die lösung bleibt ein dreizeiler ja?
aus welcher shell kommen überhaupt deine beispiele?

ich bin sowas von verwirrt und frustriert
für heute bin ich fertig :!:
egal ich schnappe mir morgen erstmal mein python buch sonst wird das nie was :?

danke und gute nacht
BlackJack

Beitragvon BlackJack » Freitag 10. November 2006, 11:25

MoR4euZ hat geschrieben:
BlackJack hat geschrieben:Wenn Du das eingelesene XML-Dokument verändern willst, dann musst Du den Inhalt des eingelesenen RunTime-Elements verändern und den eingelesenen und nun veränderten Baum in eine Datei speichern.


ok den satz verstehe ich :)
nur bekomme ich es nicht umgesetzt :roll:

die lösung bleibt ein dreizeiler ja?


Du hast jetzt schon deutlich mehr als 3 Zeilen da stehen. ;-)

Ich habe mit den drei Zeilen nur demonstrieren wollen wie man eine XML Datei schreibt, wenn man ein `Element`-Objekt hat. In der ersten Zeile habe ich ein beliebiges `Element`-Objekt erzeugt, das hast Du ja schon. In der zweiten Zeile habe ich es in einen `ElementTree` "verpackt", weil der eine Methode hat um den Baum in eine offene Datei zu schreiben. Was dann in der letzten Zeile mit `sys.stdout` demonstriert wurde. Du müsstest da natürlich eine Datei öffnen und übergeben und hinterher wieder schliessen.

aus welcher shell kommen überhaupt deine beispiele?


IPython.
Benutzeravatar
MoR4euZ
User
Beiträge: 34
Registriert: Mittwoch 18. Oktober 2006, 21:21
Wohnort: Essen
Kontaktdaten:

Beitragvon MoR4euZ » Samstag 11. November 2006, 03:22

ich habe mal wieder die halbe nacht mit python verbracht :)
auch mit elementtree habe ich weiter gekämpft ;)

klapt leider immer noch nicht :(
ich bekomme immer attribute errors vom elementinterface
aber wieso?

Code: Alles auswählen

import sys
from xml.etree import ElementTree as etree

new_runtime = 11.111111111

f = file('process.xml', 'r')
s = f.read()
root, ids = etree.XMLID(s)

doc = etree.ElementTree(file='process.xml').getroot()
rtime = root.ids['1'].getchildren()[3]
rtime.clear()
rtime.text = new_runtime

doc.write(sys.stdout)
f.close()


Code: Alles auswählen

doc.write(sys.stdout)
AttributeError: _Elementinterface instance has no attribute to write

rtime = root.ids['1'].getchildren()[3]
AttributeError: _Elementinterface instance has no attribute 'ids'
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Samstag 11. November 2006, 05:51

`ids` hast du als eigene Variable entgegengenommen, rufst aber stattdessen mit `root.ids`ein Objektattribut auf. Mit genauem Hinsehen kann man da auch selbst drauf kommen.
Benutzeravatar
MoR4euZ
User
Beiträge: 34
Registriert: Mittwoch 18. Oktober 2006, 21:21
Wohnort: Essen
Kontaktdaten:

Beitragvon MoR4euZ » Sonntag 12. November 2006, 18:29

ok hast recht root.ids war nur ein verzweifelter versuch von mir ;)
der attributeerror ist nun weg
mit doc.getroot() kommt kein attributeerror mehr

ABER :D

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from xml.etree import ElementTree as etree

xmldoc = 'process.xml'
new_runtime = 11.111111111

f = file(xmldoc, 'r')
s = f.read()
root, id = etree.XMLID(s)

doc = etree.ElementTree(file=xmldoc)
doc.getroot()
rtime = id['1'].getchildren()[3]
rtime.clear()
rtime.text = new_runtime

doc.write(file=xmldoc)
f.close()


mein xmlfile wird leider nicht richtig geschrieben

es stimmt sicher was in zeile 15 nicht
nur keine ahnung was :(

müsste es nicht
rtime = doc.getroot().id['1'].getchildren()[3]
lauten?

Code: Alles auswählen

<Process_db>
    <Process id="1">
        <LongName>Calculator</LongName>
        <ShortName>calc</ShortName>
        <Path>C:\WINDOWS\system32\calc.exe</Path>
        <RunTime>19.999999999</RunTime>
    </Process>
    <Process id="2">
        <LongName>WordPad</LongName>
        <ShortName>rtf</ShortName>
        <Path>C:\WINDOWS\system32\write.exe</Path>
        <RunTime />
    </Process>
    <Process id="3">
        <LongName>Solitaer</LongName>
        <ShortName>sol</ShortName>
        <Path>C:\WINDOWS\system32\sol.exe</Path>
        <RunTime />
    </Process>
</Process_db>


wieso wird das roottag (</Process_db>) mit doc.getroot() nicht erkannt?
die ersten beiden zeilen sind weg :)
und ich will ja nur den ersten wert im RunTime tag ändern nicht alle drei :(

das beispiel listing5.py (ohne XMLID) von xml.com klappt wunderbar
http://www.xml.com/pub/a/2003/02/12/py-xml.html?page=2

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]