XML Verarbeitung mit lxml - Problem

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
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

Hi,

Ich habe ein XML-Dokument das beispielsweise folgendes Markup enthält:

Code: Alles auswählen

<autor>Dr. Verena Murschetz, LL.M, Universit&auml;tsassistentin, Innsbruck</autor>
Nun will ich den Vornamen und den Nachnamen mit tags umgeben, damit das dann so aussieht:

Code: Alles auswählen

<autor>Dr. <vorname>Verena</vorname> <nachname>Murschetz</nachname>, LL.M, Universit&auml;tsassistentin, Innsbruck</autor>
Den Vor und Nachnamen krieg ich aus einer DB das ist kein Problem. Ich weis allerdings nicht wie ich mit lxml in eine Element um bestimmten text ein neues Element fügen kann.

Kann mir da jemand helfen ?

Vielen Dank schon mal !
deets

Code: Alles auswählen


# -*- coding: utf-8 -*-
from lxml.etree import fromstring, Element, tostring

xml = """<autor>Dr. Verena Murschetz, LL.M, Universitätsassistentin, Innsbruck</autor>"""


doc = fromstring(xml)

for autor in doc.xpath("//autor"):
    content = autor.text
    name, rest = content.split(",", 1)
    name_tag = Element("name")
    name_tag.text = name
    name_tag.tail = rest
    autor.text = None
    autor.append(name_tag)

print tostring(doc)
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

Danke, aber das hilft mir leider nicht viel weiter (Kann aber sein das ich da was falsch verstanden habe).

Dein Snippet geht davon aus das Textteile durch "," getrennt sind, was nicht immer der Fall ist.
Weiters setzt es einfach ein tag um einen dieser Teile und nicht um bestimmte Wörter. Weiters geht der "," verloren.

Ich nehme an ich sollte jetzt in der Lage sein dein Snippet auf meine Bedürfnisse zu zuschneiden....ich kriegs aber iwie nicht hin....

Vlt. noch nen kleinen Denkanstoß ?
deets

Du hast also 2 Probleme:

- du beherrschst die lxml-API nicht. Mein Snippet war Denkanstoss dazu. Und sollte auch ausreichen, wenn du dich bemuehst.

- du brauchst erstmal eine Aufbereitung der Textdaten. Dazu hast du aber bei weitem nicht genug Beispiele geliefert, und was du noch so zur Verfuegung hast.

Zum ersten Punkt schlage ich vor, dass du einfach mal davon ausgehst deine Informationen aufbereitet zu haben wie du sie haben willst, und dann einfach mal die gewuenschte XML-Struktur aufbaust. Versuch dich daran, und wenn's Probleme gibt, zeig was du gemacht hast.

Und zum zweiten - da wirst du noch einiges nachliefern muessen. Je nach dem was du da vorliegen hast, ist das allerdings alles andere als trivial.
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

Okay ich hab jetzt hinbekommen, jedoch mit PyParsing.
Das was ich wollte war mit lxml einfach nicht zu machen.
BlackJack

@patmaster: Du meinst mit `lxml` alleine und hoffentlich nicht dass Du jetzt XML ohne eine entsprechende Bibliothek manipulierst.

Das Parsen von Freitext ist mit `lxml` natürlich nicht möglich, denn das was Du da innerhalb des ``<autor>``-Tags verarbeiten möchtest sind ja struktutrierte Daten, die eher unstrukturiert als Freitext gespeichert sind.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

patmaster hat geschrieben:Okay ich hab jetzt hinbekommen, jedoch mit PyParsing.
Klingt doch gut!

Das was ich wollte war mit lxml einfach nicht zu machen.
Klingt eher beunruhigend... `lxml` dient zur Verarbeitung von XML - das brauchst Du imho doch aber für das Erstellen von neuen Tags!?!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

Hyperion hat geschrieben:
patmaster hat geschrieben:Okay ich hab jetzt hinbekommen, jedoch mit PyParsing.
Klingt doch gut!

Das was ich wollte war mit lxml einfach nicht zu machen.
Klingt eher beunruhigend... `lxml` dient zur Verarbeitung von XML - das brauchst Du imho doch aber für das Erstellen von neuen Tags!?!
Naja lxml hat für mich bisher immer funktioniert wenn ich Informationen extrahieren, oder hinzufügen wollte. Manipulieren ist anscheinend nicht so seine Stärke. Das Problem war einfach das ich Textteile analysieren musste, um dann ein Element herumzulegen. Vlt. ist das möglich aber ich hab's einfach nicht zusammengebracht.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Du hast BlackJacks und meinen Einwand nicht verstanden! Natürlich sollst und kannst Du mit `lxml` alleine Dein Problem nicht lösen. Es ist ja zweistufig, wie deets es ja schon ansprach. Für das Analysieren des Freitextes eignet sich etwas wie `PyParsing`, doch dann willst Du ja in Deine bestehende XML-Struktur neue Tags einbauen. Wie setzt Du letzteres also ohne `lxml` um?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

Hyperion hat geschrieben:Du hast BlackJacks und meinen Einwand nicht verstanden! Natürlich sollst und kannst Du mit `lxml` alleine Dein Problem nicht lösen. Es ist ja zweistufig, wie deets es ja schon ansprach. Für das Analysieren des Freitextes eignet sich etwas wie `PyParsing`, doch dann willst Du ja in Deine bestehende XML-Struktur neue Tags einbauen. Wie setzt Du letzteres also ohne `lxml` um?
Achso.
Ich bau die mit pyparsing bzw seiner transformString() - Methode ein.
Es handelt sich dann wohl eher um Text- als um XML-Bearbeitung aber es funktioniert prima.
Man muss halt aufpassen das es nicht außer Kontrolle gerät, weil es ja für pyparsing nur mehr ein fetter String ist und nicht ein Baum.

Ist zugegeben nicht die sauberste Methode, aber ich find's jetzt nicht sooo schlimm.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Du musst nicht immer einen Full-Quote produzieren; benutze nur die Passagen, auf die Du Dich beziehst! ;-)
patmaster hat geschrieben: Es handelt sich dann wohl eher um Text- als um XML-Bearbeitung aber es funktioniert prima.
Brrr... klingt schaurig ;-) Wieso nutzt Du nicht `PyParsing` für das Zerlegen der Tag-Inhalte und baust dann mit `lxml` die neuen Knoten auf und in den Baum ein? Das wäre der sinnvolle - und imho naheliegende - Weg.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

Hyperion hat geschrieben:Brrr... klingt schaurig ;-) Wieso nutzt Du nicht `PyParsing` für das Zerlegen der Tag-Inhalte und baust dann mit `lxml` die neuen Knoten auf und in den Baum ein? Das wäre der sinnvolle - und imho naheliegende - Weg.
Weil es aufwändiger gewesen wäre.
Steinigt mich, aber ich bin eher jemand der den einfachen weg geht, als sich Gedanken darüber zu machen was wohl die weite Welt der Entwickler davon halten würde :K
Erst alles zerlegen und dann wieder zusammenstückeln....nääää :mrgreen:

/edit: Okay hab noch mal darüber nachgedacht. Sich mit lxml nur das autor tag zu holen und nur das dann mit pyparsing umzuformen wäre wohl wirklich sauberer gewesen...tja...man lernt nie aus :)
Viel komplizierter ist es aber immer noch :P
BlackJack

@patmaster: Das Problem bei so etwas ist, dass du damit den eigentlichen Vorteil von XML nicht nutzt, nämlich dass das ein standardisiertes Format ist, auf dem man mit allen Möglichen Werkzeugen arbeiten kann die XML verstehen und produzieren können. Dein Programm operiert nicht auf XML, dass heisst es kann passieren dass Du Daten verarbeiten kannst die kein gültiges XML sind, aber auch dass Du mit Dateien, die sehr wohl gültiges XML sind, *nicht* klar kommst. Auf der anderen Seite ist nicht sichergestellt, dass Deine Ausgabedaten gültiges XML sind. Damit läufst Du Gefahr, dass die Ausgabe nicht mehr mit XML-Werkzeugen weiter verarbeitet werden kann.

Übrigens wäre dafür auch das Umformen des ``<autor>``-Tags rein mit `pyparsing` nicht der richtige Weg, denn neue XML-Elemente zu erzeugen ist keine Textoperation.

Ich kann mir auch irgendwie nicht vorstellen, dass es viel komplizierter ist `lxml` und `pyparsing` so zu verwenden, dass dort eine robuste Lösung bei heraus kommt.
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

BlackJack hat geschrieben:...
Ich kann mir auch irgendwie nicht vorstellen, dass es viel komplizierter ist `lxml` und `pyparsing` so zu verwenden, dass dort eine robuste Lösung bei heraus kommt.
Ich lade dich herzlich ein es zu versuchen :)
Ich bin noch nicht soooo lange bei Python, deswegen ist es natürlich durchaus möglich das mir da noch die Praxis fehlt sowas einfach mal so zu lösen.

Falls du's wirklich versuchen willst kann ich gerne Beispiel-Dokumente liefern, müsste die aber erst zensieren, da die sonst Inhalt enthalten der nicht für "Außenwelt" bestimmt ist :wink:
BlackJack

@patmaster: Challenge accepted. :-)
patmaster
User
Beiträge: 106
Registriert: Donnerstag 3. Februar 2011, 17:21

BlackJack hat geschrieben:@patmaster: Challenge accepted. :-)
Okay hier die xmls:

Code: Alles auswählen

<?xml version="1.0" encoding="ISO-8859-1"?>
<artikel typ="vorwort">
    <!--Zeitpunkt der Verlinkung: 11.11.2010 - 11:08:46-->
    <meta>
        <kategoriezuordnung>
            <mbo-kategorie>zensiert</mbo-kategorie>
            <kunden-kategorie name="filename">zensiert</kunden-kategorie>
            <kunden-kategorie name="top-artikel">zensiert</kunden-kategorie>
            <kunden-kategorie name="glp-auswahl">zensiert</kunden-kategorie>
            <rubrik>zensiert</rubrik>
        </kategoriezuordnung>
    </meta>
    <bibliographie>
        <zeitschrift>zensiert</zeitschrift>
        <jahrgang>zensiert</jahrgang>
        <seite-von>1</seite-von>
        <autor>Ihr Alexander Petsche Schriftleiter Compliance Praxis</autor>
    </bibliographie>
    <titel>zensiert</titel>
    <rumpf>
        <absatz>zensiert</absatz>        
    </rumpf>
</artikel>
und

Code: Alles auswählen

<?xml version="1.0" encoding="ISO-8859-1"?>
<artikel typ="vorwort">
    <!--Zeitpunkt der Verlinkung: 11.11.2010 - 11:08:46-->
    <meta>
        <kategoriezuordnung>
            <mbo-kategorie>zensiert</mbo-kategorie>
            <kunden-kategorie name="filename">zensiert</kunden-kategorie>
            <kunden-kategorie name="top-artikel">zensiert</kunden-kategorie>
            <kunden-kategorie name="glp-auswahl">zensiert</kunden-kategorie>
            <rubrik>zensiert</rubrik>
        </kategoriezuordnung>
    </meta>
    <bibliographie>
        <zeitschrift>zensiert</zeitschrift>
        <jahrgang>zensiert</jahrgang>
        <seite-von>1</seite-von>
        <autor>Ihr Alexander Petsche / Michi Steigleitner, <info>King of the Authors</info></autor>
    </bibliographie>
    <titel>zensiert</titel>
    <rumpf>
        <absatz>zensiert</absatz>        
    </rumpf>
</artikel>
Der gewünschte Output ist denk ich klar. (Falls nicht bitte in den 1. Post schauen.)
Antworten