I am trying to write a function that will take an xml object, an arbitrary number of tags, defined by tuples containing a tag name, attribute and attribute value (e.g ('tag1', 'id', '1')) and return the most specific node possible. My code is below:
from xml.dom import minidom
def _search(object, *pargs):
if len(pargs) == 0:
print "length of pargs was zero"
return object
else:
print "length of pargs is %s" % len(pargs)
if pargs[0][1]:
for element in object.getElementsByTagName(pargs[0][0]):
if element.attributes[pargs[0][1]].value == pargs[0][2]:
_search(element, *pargs[1:])
else:
if object.getElementsByTagName(pargs[0][0]) == 1:
_search(element, *pargs[1:])
def main():
xmldoc = minidom.parse('./example.xml')
tag1 = ('catalog_item', 'gender', "Men's")
tag2 = ('size', 'description', 'Large')
tag3 = ('color_swatch', '', '')
args = (tag1, tag2, tag3)
node = _search(xmldoc, *args)
node.toxml()
if __name__ == "__main__":
main()
Unfortunately, this doesn't seem to work. Here's the output when I run the script:
$ ./secondsearch.py
length of pargs is 3
length of pargs is 2
length of pargs is 1
Traceback (most recent call last):
File "./secondsearch.py", line 35, in <module>
main()
File "./secondsearch.py", line 32, in main
node.toxml()
AttributeError: 'NoneType' object has no attribute 'toxml'
Why isn't the 'if len(pargs) == 0' clause being exercised? If I do manage to get the xml object returned to my main method, can I then pass the object into some other function (which could change the value of the node, or append a child node, etc.)?
Background: Using python to automate testing processes, environment is is cygwin on winxp/vista/7, python version is 2.5.2. I would prefer to stay within the standard library if at all possible.
Here's the working code:
def _search(object, *pargs):
if len(pargs) == 0:
print "length of pargs was zero"
else:
print "length of pargs is %s" % len(pargs)
for element in object.getElementsByTagName(pargs[0][0]):
if pargs[0][1]:
if element.attributes[pargs[0][1]].value == pargs[0][2]:
return _search(element, *pargs[1:])
else:
if object.getElementsByTagName(pargs[0][0]) == 1:
return _search(element, *pargs[1:])
return object