Seite 1 von 1

XML DOM AttributeError: 'NoneType' object has no attribute '

Verfasst: Samstag 15. Januar 2011, 14:59
von BlackMamba
Hallo,

ich versuche mich gerade an xml und habe ein Beispiel aus den Python-Buch von Opengalileo genommen.

Generell verstanden habe ich, was das Programm macht.
Das einlesen von xml Datei klappt auch super. Allerdings wenn ich xml Dateien schreiben will, bekomme ich eine sehr "komische" Fehlermeldung.
Ich habe das Orakel Google bereits befragt, aber bin aus den Antworten da nicht so ganz schlau geworden.

Hier die Fehlermeldung:
Traceback (most recent call last):
File "...XMLGenerator/src/XMLGenerator.py", line 62, in <module>
schreibe_dict(eintraege,"ausgabe.xml")
File "...XMLGenerator/src/XMLGenerator.py", line 53, in schreibe_dict
tag_dict.appendChild(tag_eintrag)
File "/usr/lib/python2.6/xml/dom/minidom.py", line 121, in appendChild
_clear_id_cache(self)
File "/usr/lib/python2.6/xml/dom/minidom.py", line 1471, in _clear_id_cache
node.ownerDocument._id_cache.clear()
AttributeError: 'NoneType' object has no attribute '_id_cache'
Wie gesagt, mit der letzten Zeile:
AttributeError: 'NoneType' object has no attribute '_id_cache'
kann ich garnichts anfangen.

Hauptsächlich meckert er über die Zeile:

Code: Alles auswählen

 tag_dict.appendChild(tag_eintrag)
Hat jemand eine Idee oder einen Tipp?


Anbei noch der Code:

Code: Alles auswählen

import xml.dom.minidom as dom


def _knoten_auslesen(knoten): 
    return eval("%s('%s')" % (knoten.getAttribute("typ"), 
                              knoten.firstChild.data.strip()))

def lade_dict(dateiname): 
    d = {} 
    baum = dom.parse(dateiname)

    for eintrag in baum.firstChild.childNodes: 
        if eintrag.nodeName == "question": 
            schluessel = wert = None

            for knoten in eintrag.childNodes: 
                if knoten.nodeName == "string": 
                    schluessel = _knoten_auslesen(knoten) 
                elif knoten.nodeName == "query": 
                    wert = _knoten_auslesen(knoten)
                
            d[schluessel] = wert 
    return d

def _erstelle_eintrag(schluessel, wert): 
    tag_eintrag = dom.Element("question") 
    tag_schluessel = dom.Element("string") 
    tag_wert = dom.Element("query")

    tag_schluessel.setAttribute("typ", type(schluessel).__name__) 
    tag_wert.setAttribute("typ", type(wert).__name__)

    #hier muss ich dann die SPARQL Querie an den Server schicken und die Antworten hinzufuegen.
    text = dom.Text() 
    text.data = str(schluessel) 
    tag_schluessel.appendChild(text)

    text = dom.Text() 
    text.data = str(wert) 
    tag_wert.appendChild(text)

    tag_eintrag.appendChild(tag_schluessel) 
    tag_eintrag.appendChild(tag_wert) 
    return tag_eintrag

def schreibe_dict(d, dateiname): 
    baum = dom.Document() 
    tag_dict = dom.Element("musicbrainz-dataset") 
    baum.appendChild(tag_dict)

    for schluessel, wert in d.iteritems(): 
        tag_eintrag = _erstelle_eintrag(schluessel, wert) 
        tag_dict.appendChild(tag_eintrag)
        #tag_dict.appendChild(self,tag_eintrag)

    f = open(dateiname, "w") 
    baum.writexml(f, "", "\t", "\n") 
    f.close()


eintraege=lade_dict("test.xml")
schreibe_dict(eintraege,"ausgabe.xml")

Danke!

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Samstag 15. Januar 2011, 16:21
von /me
Ich bin mit minidom nicht sonderlich vertraut (lxml ist halt schöner), aber ein Blick in die minidom-Dokumentation scheint anzudeuten, dass man Elemente explizit im Kontext des Dokuments erstellen muss. Ich kann mich hier aber natürlich täuschen da ich minidom schon vor Ewigkeiten zu den Akten gelegt habe.

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Samstag 15. Januar 2011, 16:39
von BlackMamba
ist denn das mit lxml noch einfach möglich? bzw besser möglich?

Dann würde ich mir nämlich in lxml mal anschauen, wie man damit xml Dateien auslesen und erzeugen kann.

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Samstag 15. Januar 2011, 16:45
von cofi
Ja. Alternativ kannst du auch `xml.etree.ElementTree` nehmen. Aber tu dir einen Gefallen und meide minidom.

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Samstag 15. Januar 2011, 16:51
von BlackMamba
Hey,

hab mir jetzt gerade mal ein Tutorial rausgesucht zu lxml,
mal schauen, wie ich damit zurecht komme.

Der Abend ist ja noch lang :-)

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Samstag 15. Januar 2011, 19:30
von problembär
Sag' mal bitte bescheid, wenn Du zu lxml wechselst.
Ich nutze immer noch minidom und würde mir sonst Dein Problem mal anschauen. Hat natürlich keinen Zweck, wenn Du wechselst (was ok ist).

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Samstag 15. Januar 2011, 19:36
von BlackMamba
@problembär:
das wäre echt super.

hab mir jetzt mal lxml angeschaut, aber ich finde das längst nicht so intuitiv wie minidom.
Ich würde also lieber minidom weiter benutzten und nicht wchseln.

Aber wie gesagt, zu dem Fehler finde ich einfach nichts.

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Samstag 15. Januar 2011, 21:29
von BlackMamba
ich habe jetzt nochmal was anderes probiert:

Code: Alles auswählen

import xml.dom.minidom as dom
import xml.dom
 
# Dokument erzeugen
implement = xml.dom.getDOMImplementation()
doc = implement.createDocument(None, "musicbrainz-dataset", None)


def _knoten_auslesen(knoten): 
    return eval("%s('%s')" % (knoten.getAttribute("typ"), 
                              knoten.firstChild.data.strip()))

def lade_dict(dateiname): 
    d = {} 
    baum = dom.parse(dateiname)

    for eintrag in baum.firstChild.childNodes: 
        if eintrag.nodeName == "question": 
            schluessel = wert = None

            for knoten in eintrag.childNodes: 
                if knoten.nodeName == "string": 
                    schluessel = _knoten_auslesen(knoten) 
                elif knoten.nodeName == "query": 
                    wert = _knoten_auslesen(knoten)
                
            d[schluessel] = wert 
    return d

def schreibe_dict(d, dateiname): 
    for schluessel, wert in d.iteritems(): 
        #tag_dict.appendChild(self,tag_eintrag)
        questionElem = doc.createElement("Question")
        doc.appendChild(questionElem)
        nameElem = doc.createElement("String")
        questionElem.appendChild(nameElem)
        nameTextElem = doc.createTextNode(schluessel)
        nameElem.appendChild(nameTextElem)
        
        querryElem = doc.createElement("Query")
        questionElem.appendChild(querryElem)
        anschriftTextElem = doc.createTextNode(wert)
        querryElem.appendChild(anschriftTextElem)
        doc.documentElement.appendChild(querryElem)
    
    datei = open(dateiname, "w")
    doc.writexml(datei, "\n", "  ")
    datei.close()


eintraege=lade_dict("test.xml")
print(eintraege)
schreibe_dict(eintraege,"ausgabe.xml")
Allerdings bekomme ich jetzt als Fehlermeldung:
Traceback (most recent call last):
File ".../XMLGenerator/src/XMLGenerator.py", line 78, in <module>
schreibe_dict(eintraege,"ausgabe.xml")
File ".../XMLGenerator/src/XMLGenerator.py", line 56, in schreibe_dict
doc.appendChild(questionElem)
File "/usr/lib/python2.6/xml/dom/minidom.py", line 1552, in appendChild
"two document elements disallowed")
xml.dom.HierarchyRequestErr: two document elements disallowed
Ich vermute, dass ich irgendwie Root und Element vertausche, bzw die beiden einander überschneiden.

Aber ich sehe nicht wo, ihr zufällig?

Danke!

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Samstag 15. Januar 2011, 21:45
von BlackMamba
Fehler gefunden!

jetzt läuft alles.


So gehts richtig:

Code: Alles auswählen

import xml.dom.minidom as dom
import xml.dom
 
# Dokument erzeugen
implement = xml.dom.getDOMImplementation()
doc = implement.createDocument(None, "musicbrainz-dataset", None)


def _knoten_auslesen(knoten): 
    return eval("%s('%s')" % (knoten.getAttribute("typ"), 
                              knoten.firstChild.data.strip()))

def lade_dict(dateiname): 
    d = {} 
    baum = dom.parse(dateiname)

    for eintrag in baum.firstChild.childNodes: 
        if eintrag.nodeName == "question": 
            schluessel = wert = None

            for knoten in eintrag.childNodes: 
                if knoten.nodeName == "string": 
                    schluessel = _knoten_auslesen(knoten) 
                elif knoten.nodeName == "query": 
                    wert = _knoten_auslesen(knoten)
                
            d[schluessel] = wert 
    return d

def schreibe_dict(d, dateiname): 
    for schluessel, wert in d.iteritems(): 
        #tag_dict.appendChild(self,tag_eintrag)
        questionElem = doc.createElement("Question")
        #doc.appendChild(questionElem)
        nameElem = doc.createElement("String")
        questionElem.appendChild(nameElem)
        nameTextElem = doc.createTextNode(schluessel)
        nameElem.appendChild(nameTextElem)
        
        querryElem = doc.createElement("Query")
        questionElem.appendChild(querryElem)
        anschriftTextElem = doc.createTextNode(wert)
        querryElem.appendChild(anschriftTextElem)
        #questionElem.documentElement.appendChild(querryElem)
        
        doc.documentElement.appendChild(questionElem)
        
    datei = open(dateiname, "w")
    doc.writexml(datei, "\n", "  ")
    datei.close()


eintraege=lade_dict("test.xml")
print(eintraege)
schreibe_dict(eintraege,"ausgabe.xml")

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Samstag 15. Januar 2011, 22:59
von /me
Jetzt solltest du nur noch ein wenig aufräumen.

doc brauchst du nicht auf Modulebene und kannst es daher in die Funktion schreibe_dict() verlagern.

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Samstag 15. Januar 2011, 23:05
von BlackMamba
oh,

ja, da hast du recht :-)


mache ich mal sofort!

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Sonntag 16. Januar 2011, 04:13
von Leonidas
Aufgabe an den geneigten Leser: den Code in 1/4 der Zeilen mit lxml implementieren :)

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Sonntag 16. Januar 2011, 10:45
von BlackMamba
wie geht denn das mit lxml?

ich hab das nicht hinbekommen.
(Ich hab auch seid bestimmt 2 Jahren kein Python mehr angefasst)


Wobei das ja jetzt nur ein Teil des Programmes ist, dazu gehören noch einige ander selbs geschriebene Parser und noch Server Aufrufe etc... Ansonsten würde das Programm ja so jetzt nicht viel machen :-D

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Sonntag 16. Januar 2011, 11:24
von BlackJack
Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import __builtin__
from itertools import imap
from lxml import etree
from lxml.etree import Element, ElementTree, SubElement


def load(filename):
    def convert_content(node):
        return __builtin__.get(node.get('typ'))(node.text.strip())
    
    def convert_node(node):
        return [convert_content(node.find(x)) for x in ['string', 'query']]
    
    return dict(imap(convert_node, etree.parse(filename).xpath('//question')))


def save(mapping, filename):
    root = Element('musicbrainz-dataset')
    for key, value in mapping.iteritems():
        question_node = SubElement(root, 'Question')
        SubElement(question_node, 'String').text = key
        SubElement(question_node, 'Query').text = value
    ElementTree(root, pretty_print=True).write(filename)


def main():
    mapping = load('test.xml')
    print mapping
    save(mapping, 'ausgabe.xml')


if __name__ == "__main__":
    main()

Re: XML DOM AttributeError: 'NoneType' object has no attribu

Verfasst: Sonntag 16. Januar 2011, 11:59
von BlackMamba
das sieht natürlich einiges einfacher aus, aber das habe ich irgendwie nicht so hinbekommen.


Aber ich werde es mir nachher mal in Ruhe anschauen.
Aber ich habe gestern schon festgestellt, Python an sich ist sehr sehr angenehm, ich denke, damit werde ich öfters jetzt was machen.

Danke!!