Seite 1 von 1
Zeilen- und Spaltennummer mit ElementTree
Verfasst: Freitag 10. Dezember 2010, 23:31
von Jerry
Moin,
Ich schreibe grade an einem kleinen Programm, in dem unter anderem eine xml Datei ausgewertet werden muss. Beim parsen möchte ich gerne dem User eine Rückmeldung geben, falls irgendwo Mist drin steht, obwohl es sich um syntaktisch korrektes Xml handelt. Ein kleines Beispiel:
Code: Alles auswählen
<group name="General">
<entry name="option1" type="String">
<default>Default String</default>
<entry name="option2" type="Int">
<default>zwölf</default> <--HIER
</entry>
</group>
Wie kann ich nun beim parsen (vorzugsweise mit ElementTree) die genaue Zeilen- und optimalerweise auch die Spaltenummer rauskriegen?
Gruß, Dennis
Re: Zeilen- und Spaltennummer mit ElementTree
Verfasst: Samstag 11. Dezember 2010, 00:42
von Hyperion
In diesem Falle würde ich mittels XML Schema eine Grammatik für das XML Format spezifizieren (oder mit Relax, würde mich auch mal interessieren) und dann den Validator von lxml darauf loslassen. Damit erhältst Du eine schöne Fehlermeldung iirc inkl. Zeilen und Spaltenummer.
Re: Zeilen- und Spaltennummer mit ElementTree
Verfasst: Samstag 11. Dezember 2010, 01:01
von BlackJack
@Jerry: `lxml.etree` kennt auf `Element`-Objekten ein `sourceline`-Attribut:
Code: Alles auswählen
In [56]: doc.xpath('entry[@name="option2"]/default')[0].sourceline
Out[56]: 5
Re: Zeilen- und Spaltennummer mit ElementTree
Verfasst: Samstag 11. Dezember 2010, 02:25
von Jerry
@Hyperion
Ich hätte vielleicht erwähnen sollen, dass es bereits ein
Xml Schema gibt^^ Aber wie du an dem Beispiel sehen kannst, ändert sich ja der erlaubte Wert des default-Elements in Bezug auf das type-Attribut des entry-Elements(und da hörts leider noch nicht auf). Ich bin allerdings noch nicht dahinter gekommen wie ich das im Schema definieren soll bzw. ob das so überhaupt möglich ist...
@BlackJack
Danke, dass wusste ich noch nicht. Aber (irgendwas ist ja immer -.-), ich zögere da ein bisschen, lxml zu verwenden (obwohl es mir das Leben auch an anderer Stelle einfacher machen würde!). Mein Programm kann nämlich nicht nur als eigenständige Anwendung laufen, sondern auch in anderen Anwendungen genutzt werden (PyKDE-Anwendungen, ausschließlich), daher möchte ich nur sehr ungern weitere Abhängigkeiten haben. Ich könnte natürlich die Qt eigenen Klassen benutzen (die sind ja gegeben), aber das ganze Geraffel mit QString und QStringRef ist einfach nicht schön, ich bevorzuge da doch eine native Python Lösung, geht das nicht irgendwie mit dem von Python mitgelieferten ElementTree Modul? Ich mag die ElementTree-Api
Vielen Dank für die Antworten!
Re: Zeilen- und Spaltennummer mit ElementTree
Verfasst: Samstag 11. Dezember 2010, 02:45
von Hyperion
Ach so... hm... da könnte man sich natürlich fragen, wieso das so sein muss und ob das nicht schlechtes Design des XML-Formates ist
Würdest Du nicht "stumpf" <entry>-Tags nutzen, sondern z.B. <entryInt>, <entryString> usw., so könntest Du das via XML Schema rausbekommen. Andere Standardattribute können die entries ja ruhig haben. Oder man führt eine neue Ebene unterhalb von <entry> ein, die dann den folgenden Datentypen einschränkt.
Aber bevor ich lange philosophiere, vielleicht ist das ja auch vorgegeben und Du musst jetzt damit klarkommen

Re: Zeilen- und Spaltennummer mit ElementTree
Verfasst: Samstag 11. Dezember 2010, 02:51
von BlackJack
@Jerry: Ich weiss nicht ob ich den letzten Satz vor dem "Frowney" richtig interpretiere, aber Du weisst, dass die API von `lxml.etree` eine etwas erweiterte `ElementTree`-API ist!?
Re: Zeilen- und Spaltennummer mit ElementTree
Verfasst: Samstag 11. Dezember 2010, 12:43
von lunar
@Hyperion: Wenn das schlechtes Design wäre, dann wäre XSD selbst schlecht entworfen. Es ist aber halt nun mal so, dass man bestimmte Bedingungen (e.g. Typkorrektheit) grammatikalisch nicht prüfen kann, und XSD ist eben nur ein Grammatik-Spezifikation. Ich würde im Gegenteil eher "entryInt", "entryString", usw. für schlechtes Design halten, denn das ist weder flexibel, noch einfach zu verarbeiten, und zudem aufgeblasen.
Re: Zeilen- und Spaltennummer mit ElementTree
Verfasst: Samstag 11. Dezember 2010, 14:39
von Hyperion
lunar hat geschrieben:@Hyperion: Wenn das schlechtes Design wäre, dann wäre XSD selbst schlecht entworfen. Es ist aber halt nun mal so, dass man bestimmte Bedingungen (e.g. Typkorrektheit) grammatikalisch nicht prüfen kann, und XSD ist eben nur ein Grammatik-Spezifikation.
Naja, in diesem Falle nicht, da sich die Typen "dynamisch", je nach Wert des Attributes in einem Tag, darauf folgend ändern. Ansonsten kann man Typen ja eben schon prüfen.
Ich würde im Gegenteil eher "entryInt", "entryString", usw. für schlechtes Design halten, denn das ist weder flexibel, noch einfach zu verarbeiten, und zudem aufgeblasen.
Die Namen sind vielleicht schlecht gewählt gewesen und aufgeblasen mag es auch sein, aber damit wäre das Validieren eben möglich. Natürlich muss man Prioritäten setzen, was einem da lieber / wichtiger ist. Will ich alles bis ins kleineste Detail überprüfen, wird das Dokument zwangsläufig komplexer, zudem wenn man dazu noch universell bleiben will. WSDL, SOAP und Co. fallen mir da spontan ein.
Ich habe das
Dokument mal entsprechend angepasst und eine
Schemadatei angelegt, sowie das
Validieren gezeigt.
Re: Zeilen- und Spaltennummer mit ElementTree
Verfasst: Samstag 11. Dezember 2010, 18:39
von Jerry
Hyperion hat geschrieben:Aber bevor ich lange philosophiere, vielleicht ist das ja auch vorgegeben und Du musst jetzt damit klarkommen

Yep, so siehts aus

Großartig ändern kann ich da jetzt nix...
BlackJack hat geschrieben:@Jerry: Ich weiss nicht ob ich den letzten Satz vor dem "Frowney" richtig interpretiere, aber Du weisst, dass die API von `lxml.etree` eine etwas erweiterte `ElementTree`-API ist!?
Ja, weiss ich. Aber die beiden ähneln sich doch sehr, und beide sind mir viel lieber als der ganze Rest. Allein um Attribute auszulesen muss ich mit den Qt Klassen sowas schreiben
, was mich nebenbei auch zwingt QRegExp zu benutzen, ich muss auch auf QString Methoden wir trimmed(), oder toLower() anstatt strip() und lower() zurückgreifen, oder ich caste mich doof und dämlich. Ganz davon abgesehen, dass das alles obsolet wird, sobald nach python3 portiert wird...