Problem mit lxml

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.
blubber
User
Beiträge: 123
Registriert: Montag 19. März 2007, 09:08

Montag 3. November 2008, 11:02

Hi,

hab da ein Problem mit lxml, hab jetzt schon zweimal die Docu durchgelesen und rumprobiert aber ich bekomms einfach nicht gebacken :oops:
Und zwar hab ich eine test.xml:

Code: Alles auswählen

 <test name = "Test1"> 
   <datensatz ID = "1"> 
       <daten 
              Vorname="hans" 
              Nachname = "mustermann"/> 
   </datensatz> 
</test> 
Dazu noch ein Python File:

Code: Alles auswählen

from lxml import etree

XML = etree.parse("test.xml")
temp = etree.tostring(XML)
print temp
Jo, dieses parsed mir meine XML, packts als String in die Variable temp und printed das ganze Zeugs raus.
Nun raff ich aber einfach nicht, wie ich z.B. den Vornamen von "hans" auf "otto" ändern kann.
Könnte mir jemand auf die Sprünge helfen?
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Montag 3. November 2008, 11:30

Wurde Dir diese Frage nicht schon hier beantwortet?
MfG
HWK
blubber
User
Beiträge: 123
Registriert: Montag 19. März 2007, 09:08

Montag 3. November 2008, 11:35

ja nicht direkt, weil ich ja erstmal keinen String als Quelle hab, sondern ein XML File. Aber habs nun hinbekommen.
XML einlesen -> zu string konvertieren -> als string wieder einlesen und dann die Schleife von BlackJack nehmen.
Keine Ahnung, ob das von der Logik her so konsequent ist, aber es funktioniert.
Ganz kapiert hab ich das LXML noch nicht wirklich.
Benutzeravatar
cofi
Moderator
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Montag 3. November 2008, 11:57

Ob aus einem String oder einer Datei ist für lxml unerheblich. Das ändert nur die Initialisierung. lxml.etree operiert immer auf einem elementtree, den erzeugst du entweder aus einem String oder aus einer Datei.

Code: Alles auswählen

from StringIO import StringIO
from lxml import etree
xml_string = """<test name = "Test1">
   <datensatz ID = "1">
       <daten
              Vorname="hans"
              Nachname = "mustermann"/>
   </datensatz>
</test>"""
parsed = etree.parse(StringIO(xml_string))
print etree.tostring(parsed)
StringIO simuliert ein File-Object aus einem String. Vielleicht geht dir das Licht ja damit auf ;)
blubber
User
Beiträge: 123
Registriert: Montag 19. März 2007, 09:08

Montag 3. November 2008, 12:37

hm ok, wie ich grad festgestellt habe, komm ich doch nicht weiter.
Denn meine XML enthält natürlich mehrere Datensätze (mit Namen und Vornamen) und ich möchte bei

Code: Alles auswählen

<Gesamt zeit = "heute">
	<test name = "Test1"> 
	   <datensatz ID = "1"> 
	       <daten 
	              Vorname="otto" 
	              Nachname = "mustermann"/> 
	   </datensatz> 
	   <datensatz ID = "5"> 
	       <daten 
	              Vorname="hans" 
	              Nachname = "lummelmann"/> 
	   </datensatz> 
	</test>
	<test name = "Test2">
	</test>
	<test name = "Test3">
	</test>
</Gesamt>
zum Beispiel NUR den Namen hans nach otto ändern, und nicht ALLE Vornamen....
Benutzeravatar
cofi
Moderator
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Montag 3. November 2008, 13:30

Entweder könntest du die daten deiner datensätze traversieren und dabei die `Vorname'-Attribute vergleichen, oder du schaust dir XPath und den entsprechenden Teil der lxml-Dokumentation an.
blubber
User
Beiträge: 123
Registriert: Montag 19. März 2007, 09:08

Montag 3. November 2008, 13:38

naja, ist ja nicht so, als ob ich mir das nicht schon durchgelesen und rumprobiert hätte...
blubber
User
Beiträge: 123
Registriert: Montag 19. März 2007, 09:08

Montag 3. November 2008, 14:23

Kann man eigentlich direkt ein Attribut setzen? Also ohne, dass man irgendwelche Schleifen durchlaufen muss?
Denn mir ist quasi alles bekannt, also ich weis zum Beispiel:

zeit = "heute"
name = "Test1"
ID = "5"
Vorname = "hans"

Mir ist also grundsätzlich der komplette Pfad zum "Zielattribut" das ich ändern möchte bekannt.
Das müsste dann doch auch ohne Schleife gehen oder?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 3. November 2008, 14:45

blubber hat geschrieben:Mir ist also grundsätzlich der komplette Pfad zum "Zielattribut" das ich ändern möchte bekannt.
Das müsste dann doch auch ohne Schleife gehen oder?
Logisch, cofi hat ja XPath bereits erwähnt. Alternativ kann man da sicher auch mit CSS-Selektoren etwas machen, wenn einem XPath zu kompliziert ist.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
blubber
User
Beiträge: 123
Registriert: Montag 19. März 2007, 09:08

Montag 3. November 2008, 15:11

Hab mir die Doku zu Xpath ja durchgelesen, aber wirklich gecheckt hab ich das nicht. Bzw. das was in der Doku steht war (aus meiner Sicht) für mein Problem nicht hilfreich, vielleicht fehlt mir da aber auch die Weitsicht die man benötigt, keine Ahnung.
Könnte mir denn jemand mit einem Beispiel weiterhelfen? Scheint ja nur eine Art Einzeiler zu sein wenn man direkt auf ein Attribut zugreifen kann...
lunar

Montag 3. November 2008, 15:18

cofi hat geschrieben:Ob aus einem String oder einer Datei ist für lxml unerheblich. Das ändert nur die Initialisierung. lxml.etree operiert immer auf einem elementtree, den erzeugst du entweder aus einem String oder aus einer Datei.

Code: Alles auswählen

from StringIO import StringIO
from lxml import etree
xml_string = """<test name = "Test1">
   <datensatz ID = "1">
       <daten
              Vorname="hans"
              Nachname = "mustermann"/>
   </datensatz>
</test>"""
parsed = etree.parse(StringIO(xml_string))
print etree.tostring(parsed)
StringIO simuliert ein File-Object aus einem String. Vielleicht geht dir das Licht ja damit auf ;)
"etree.fromstring()" existiert, das StringIO-Objekt ist unnötig.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Montag 3. November 2008, 16:25

Ich glaube, cofi wollte damit zeigen, wie es mit einem File bzw. Filelike-Object funktioniert, da blubber seine Datei erst als String geladen und dann den String weiter verarbeitet hat.
MfG
HWK
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 3. November 2008, 18:19

Code: Alles auswählen

from lxml import etree as ET
from lxml.cssselect import CSSSelector

root = ET.fromstring("""<Gesamt zeit = "heute">
    <test name = "Test1">
       <datensatz ID = "1">
           <daten
                  Vorname="otto"
                  Nachname = "mustermann"/>
       </datensatz>
       <datensatz ID = "5">
           <daten
                  Vorname="hans"
                  Nachname = "lummelmann"/>
       </datensatz>
    </test>
    <test name = "Test2">
    </test>
    <test name = "Test3">
    </test>
</Gesamt> """)
CSSSelector('daten[Vorname="hans"]')(root)[0].attrib['Vorname'] = 'otto'
print ET.tostring(root)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Montag 3. November 2008, 20:30

Das ist jetzt aber kein gutes Beispiel für "wenn einem XPath zu kompliziert ist":

Code: Alles auswählen

root.xpath('//daten[@Vorname="hans"]')[0].attrib['Vorname'] = 'otto'
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 3. November 2008, 22:51

BlackJack hat geschrieben:Das ist jetzt aber kein gutes Beispiel für "wenn einem XPath zu kompliziert ist"
Nein, eher nicht. Aber ich finde den CSS-Selektor trotzdem marginal einfacher zu verstehen, eben weil da kein ``//`` und ``@`` vorkommt, wo man erst nachschauen müsste was das bedeutet. Insbesondere da es ja wie der CSS-Selektor vormacht, auch ohne geht. Aber ich finde generell CSS-Selektoren angenehm, bin wohl schon zu sehr jQuery-geschädigt, von daher halte ich den Einsatz davon durchaus vertretbar.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Antworten