Minidom.Node doesn't call __getattr__ | Newbie | | Join Date: Mar 2008
Posts: 5
| |
I'm using minidom to parse XML and to simplify accessing child nodes, I'm trying to implement __getattr__ for the Node class. Yes, I know what most of you will think of that; I'll just have to be careful, won't I. ;) - import xml
-
from xml.dom.minidom import parseString
-
-
def getChild(self, name):
-
print "Getting child"
-
return self.getElementsByTagName(name)[0]
-
-
xml.dom.minidom.Node.__getattr__ = getChild
-
-
xmlDoc = parseString('''<?xml version="1.0" encoding="ISO-8859-1"?>
-
<CATALOG>
-
<cd>
-
<title>Empire Burlesque</title>
-
<ARTIST>Bob Dylan</ARTIST>
-
<COUNTRY>USA</COUNTRY>
-
<COMPANY>Columbia</COMPANY>
-
<PRICE>10.90</PRICE>
-
<YEAR>1985</YEAR>
-
</cd>
-
<cd>
-
<title>Hide your heart</title>
-
<ARTIST>Bonnie Tylor</ARTIST>
-
<COUNTRY>UK</COUNTRY>
-
<COMPANY>CBS Records</COMPANY>
-
<PRICE>9.90</PRICE>
-
<YEAR>1988</YEAR>
-
</cd>
-
</CATALOG>''')
-
-
xmlRoot = xmlDoc.childNodes[0]
-
print xmlRoot.__getattr__
-
print xmlRoot.cd.title.childNodes[0].nodeValue
outputs: - <bound method Element.getChild of <DOM Element: CATALOG at 0x1c50850>>
-
File "C:\Users\Tuomas\Projektit\wrestlevania\ezXML.py", line 31, in <module>
-
print xmlRoot.cd.title.childNodes[0].nodeValue
-
AttributeError: Element instance has no attribute 'cd'
As far as I can tell, everything works fine, except __getattr__ never gets called. Can anyone help me understand why that is or how to work around it?
|  | Needs Regular Fix | | Join Date: Jul 2007 Location: Durham, NC
Posts: 313
| | | re: Minidom.Node doesn't call __getattr__
If you're trying to call __getattr__ you need ().
| | Newbie | | Join Date: Mar 2008
Posts: 5
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by jlm699 If you're trying to call __getattr__ you need (). Not trying to call it - I'm overriding it.
|  | Needs Regular Fix | | Join Date: Jul 2007 Location: Durham, NC
Posts: 313
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by ArseAssassin Not trying to call it - I'm overriding it. No I know that... but you still need the (name) arguments that getChild needs
| | Newbie | | Join Date: Mar 2008
Posts: 5
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by jlm699 No I know that... but you still need the (name) arguments that getChild needs I'm not sure what you're getting at. getChild is just an implementation of the special method __getattr__, which should be called when I'm trying to access attributes that aren't defined.
|  | Needs Regular Fix | | Join Date: Jul 2007 Location: Durham, NC
Posts: 313
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by ArseAssassin I'm not sure what you're getting at. getChild is just an implementation of the special method __getattr__, which should be called when I'm trying to access attributes that aren't defined. But aren't you over-riding __getattr__ with getChild ? The way that your code is setup, instead of __getattr__ being called, it calls for getChild... I don't know, maybe I'm misunderstanding what you're trying to accomplish in this code... Where does the .cd. method come from since it's not an attribute of the class that you are trying to call it from?
|  | Moderator | | Join Date: Oct 2006 Location: Nashville, TN
Posts: 1,563
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by ArseAssassin I'm using minidom to parse XML and to simplify accessing child nodes, I'm trying to implement __getattr__ for the Node class. Yes, I know what most of you will think of that; I'll just have to be careful, won't I. ;) - import xml
-
from xml.dom.minidom import parseString
-
-
def getChild(self, name):
-
print "Getting child"
-
return self.getElementsByTagName(name)[0]
-
-
xml.dom.minidom.Node.__getattr__ = getChild
-
-
xmlDoc = parseString('''<?xml version="1.0" encoding="ISO-8859-1"?>
-
<CATALOG>
-
<cd>
-
<title>Empire Burlesque</title>
-
<ARTIST>Bob Dylan</ARTIST>
-
<COUNTRY>USA</COUNTRY>
-
<COMPANY>Columbia</COMPANY>
-
<PRICE>10.90</PRICE>
-
<YEAR>1985</YEAR>
-
</cd>
-
<cd>
-
<title>Hide your heart</title>
-
<ARTIST>Bonnie Tylor</ARTIST>
-
<COUNTRY>UK</COUNTRY>
-
<COMPANY>CBS Records</COMPANY>
-
<PRICE>9.90</PRICE>
-
<YEAR>1988</YEAR>
-
</cd>
-
</CATALOG>''')
-
-
xmlRoot = xmlDoc.childNodes[0]
-
print xmlRoot.__getattr__
-
print xmlRoot.cd.title.childNodes[0].nodeValue
outputs: - <bound method Element.getChild of <DOM Element: CATALOG at 0x1c50850>>
-
File "C:\Users\Tuomas\Projektit\wrestlevania\ezXML.py", line 31, in <module>
-
print xmlRoot.cd.title.childNodes[0].nodeValue
-
AttributeError: Element instance has no attribute 'cd'
As far as I can tell, everything works fine, except __getattr__ never gets called. Can anyone help me understand why that is or how to work around it? Modify getChild() slightly: - def getChild(self, name):
-
print "Getting child"
-
return self.getElementsByTagName(name)
Modify the calls: - xmlRoot = xmlDoc.childNodes[0]
-
print xmlRoot.__getattr__('cd')
-
print xmlRoot.__getattr__('cd')[0].__getattr__('title')[0].firstChild.nodeValue
-
print xmlRoot.__getattr__('ARTIST')[0].firstChild.nodeValue
Output: - >>> Getting child
-
[<DOM Element: cd at 0x100d4b8>, <DOM Element: cd at 0x100d788>]
-
Getting child
-
Getting child
-
Empire Burlesque
-
Getting child
-
Bob Dylan
-
>>>
|  | Needs Regular Fix | | Join Date: Jul 2007 Location: Durham, NC
Posts: 313
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by bvdet Modify the calls: -
print xmlRoot.__getattr__('cd')
-
That's what I was trying to say by using the (name) argument
|  | Moderator | | Join Date: Oct 2006 Location: Nashville, TN
Posts: 1,563
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by jlm699 That's what I was trying to say by using the (name) argument And you were correct!
|  | Needs Regular Fix | | Join Date: Jul 2007 Location: Durham, NC
Posts: 313
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by bvdet - xmlRoot = xmlDoc.childNodes[0]
-
print xmlRoot.__getattr__('cd')
-
print xmlRoot.__getattr__('cd')[0].__getattr__('title')[0].firstChild.nodeValue
-
print xmlRoot.__getattr__('ARTIST')[0].firstChild.nodeValue
Output: - >>> Getting child
-
[<DOM Element: cd at 0x100d4b8>, <DOM Element: cd at 0x100d788>]
-
Getting child
-
Getting child
-
Empire Burlesque
-
Getting child
-
Bob Dylan
-
>>>
In my calls I needed to modify it a little bit... -
>>> xmlRoot.__getattr__('cd').__getattr__('title').firstChild.nodeValue
-
Getting child
-
Getting child
-
u'Empire Burlesque'
-
>>> xmlRoot.__getattr__('ARTIST').firstChild.nodeValue
-
Getting child
-
u'Bob Dylan'
-
>>>
-
|  | Moderator | | Join Date: Oct 2006 Location: Nashville, TN
Posts: 1,563
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by jlm699 In my calls I needed to modify it a little bit... -
>>> xmlRoot.__getattr__('cd').__getattr__('title').firstChild.nodeValue
-
Getting child
-
Getting child
-
u'Empire Burlesque'
-
>>> xmlRoot.__getattr__('ARTIST').firstChild.nodeValue
-
Getting child
-
u'Bob Dylan'
-
>>>
-
I had modified function getChild() to return the NodeList object. Otherwise you could not access the other elements in the object. -
>>> for elem in xmlRoot.__getattr__('cd'):
-
... print elem
-
...
-
Getting child
-
<DOM Element: cd at 0xf854b8>
-
<DOM Element: cd at 0xf8b490>
-
>>>
| | Newbie | | Join Date: Mar 2008
Posts: 5
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by jlm699 In my calls I needed to modify it a little bit... -
>>> xmlRoot.__getattr__('cd').__getattr__('title').firstChild.nodeValue
-
Getting child
-
Getting child
-
u'Empire Burlesque'
-
>>> xmlRoot.__getattr__('ARTIST').firstChild.nodeValue
-
Getting child
-
u'Bob Dylan'
-
>>>
-
Well, obviously that'll work. Here's what I'm going for: http://pyref.infogami.com/__getattr__ Quote:
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self).
With any custom class I define, it will work: - >>> class example:
-
... def __init__(self):
-
... print 'Initiated'
-
...
-
>>> a = example()
-
Initiated
-
>>> def getAttribute(self, name):
-
... print name, 'was not found'
-
...
-
>>> example.__getattr__ = getAttribute
-
>>> print a.unknownAttribute
-
unknownAttribute was not found
I'm having trouble understanding why it won't work for minidom nodes.
| | Newbie | | Join Date: Mar 2008
Posts: 5
| | | re: Minidom.Node doesn't call __getattr__
I was finally able to figure it out: since the nodes I'm accessing are actually instances of the Element class and __getattr__ isn't part of its parent's (Node class) original class definition, the new instances aren't, I suppose, aware of the method's existence. It's definitely inherited since I can access it; the instances just won't know they're supposed to call it. That's what I figure anyway. Here's the working code: - import xml
-
from xml.dom.minidom import parseString
-
-
def getChild(self, name):
-
print "Getting child"
-
return self.getElementsByTagName(name)[0]
-
-
xml.dom.minidom.Element.__getattr__ = getChild
-
-
xmlDoc = parseString('''<?xml version="1.0" encoding="ISO-8859-1"?>
-
<CATALOG>
-
<cd>
-
<title>Empire Burlesque</title>
-
<ARTIST>Bob Dylan</ARTIST>
-
<COUNTRY>USA</COUNTRY>
-
<COMPANY>Columbia</COMPANY>
-
<PRICE>10.90</PRICE>
-
<YEAR>1985</YEAR>
-
</cd>
-
<cd>
-
<title>Hide your heart</title>
-
<ARTIST>Bonnie Tylor</ARTIST>
-
<COUNTRY>UK</COUNTRY>
-
<COMPANY>CBS Records</COMPANY>
-
<PRICE>9.90</PRICE>
-
<YEAR>1988</YEAR>
-
</cd>
-
</CATALOG>''')
-
-
xmlRoot = xmlDoc.childNodes[0]
-
print xmlRoot.__getattr__
-
print xmlRoot.cd.title.childNodes[0].nodeValue
Thanks for the help, guys. :)
|  | Moderator | | Join Date: Oct 2006 Location: Nashville, TN
Posts: 1,563
| | | re: Minidom.Node doesn't call __getattr__ Quote:
Originally Posted by ArseAssassin I was finally able to figure it out: since the nodes I'm accessing are actually instances of the Element class and __getattr__ isn't part of its parent's (Node class) original class definition, the new instances aren't, I suppose, aware of the method's existence. It's definitely inherited since I can access it; the instances just won't know they're supposed to call it. That's what I figure anyway. Here's the working code: - import xml
-
from xml.dom.minidom import parseString
-
-
def getChild(self, name):
-
print "Getting child"
-
return self.getElementsByTagName(name)[0]
-
-
xml.dom.minidom.Element.__getattr__ = getChild
-
-
xmlDoc = parseString('''<?xml version="1.0" encoding="ISO-8859-1"?>
-
<CATALOG>
-
<cd>
-
<title>Empire Burlesque</title>
-
<ARTIST>Bob Dylan</ARTIST>
-
<COUNTRY>USA</COUNTRY>
-
<COMPANY>Columbia</COMPANY>
-
<PRICE>10.90</PRICE>
-
<YEAR>1985</YEAR>
-
</cd>
-
<cd>
-
<title>Hide your heart</title>
-
<ARTIST>Bonnie Tylor</ARTIST>
-
<COUNTRY>UK</COUNTRY>
-
<COMPANY>CBS Records</COMPANY>
-
<PRICE>9.90</PRICE>
-
<YEAR>1988</YEAR>
-
</cd>
-
</CATALOG>''')
-
-
xmlRoot = xmlDoc.childNodes[0]
-
print xmlRoot.__getattr__
-
print xmlRoot.cd.title.childNodes[0].nodeValue
Thanks for the help, guys. :) You are welcome, and thank you for sharing what you have found out.
|  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,419 network members.
|