1
2 '''FlickrAPI uses its own in-memory XML representation, to be able to easily
3 use the info returned from Flickr.
4
5 There is no need to use this module directly, you'll get XMLNode instances
6 from the FlickrAPI method calls.
7 '''
8
9 import xml.dom.minidom
10
11 __all__ = ('XMLNode', )
15 """XMLNode -- generic class for holding an XML node
16
17 >>> xml_str = '''<xml foo="32">
18 ... <taggy bar="10">Name0</taggy>
19 ... <taggy bar="11" baz="12">Name1</taggy>
20 ... </xml>'''
21 >>> f = XMLNode.parse(xml_str)
22 >>> f.name
23 u'xml'
24 >>> f['foo']
25 u'32'
26 >>> f.taggy[0].name
27 u'taggy'
28 >>> f.taggy[0]["bar"]
29 u'10'
30 >>> f.taggy[0].text
31 u'Name0'
32 >>> f.taggy[1].name
33 u'taggy'
34 >>> f.taggy[1]["bar"]
35 u'11'
36 >>> f.taggy[1]["baz"]
37 u'12'
38
39 """
40
42 """Construct an empty XML node."""
43 self.name = ""
44 self.text = ""
45 self.attrib = {}
46 self.xml = None
47
49 """Store a node's attribute in the attrib hash."""
50 self.attrib[key] = item
51
53 """Retrieve a node's attribute from the attrib hash."""
54 return self.attrib[key]
55
56 @classmethod
58 """Recursive call to process this XMLNode."""
59
60 this_node.name = element.nodeName
61
62
63 for i in range(element.attributes.length):
64 an = element.attributes.item(i)
65 this_node[an.name] = an.nodeValue
66
67 for a in element.childNodes:
68 if a.nodeType == xml.dom.Node.ELEMENT_NODE:
69
70 child = XMLNode()
71
72
73
74 if not hasattr(this_node, a.nodeName) or a.nodeName == 'name':
75 setattr(this_node, a.nodeName, [])
76
77
78 children = getattr(this_node, a.nodeName)
79 children.append(child)
80
81 cls.__parse_element(a, child)
82
83 elif a.nodeType == xml.dom.Node.TEXT_NODE:
84 this_node.text += a.nodeValue
85
86 return this_node
87
88 @classmethod
89 - def parse(cls, xml_str, store_xml=False):
90 """Convert an XML string into a nice instance tree of XMLNodes.
91
92 xml_str -- the XML to parse
93 store_xml -- if True, stores the XML string in the root XMLNode.xml
94
95 """
96
97 dom = xml.dom.minidom.parseString(xml_str)
98
99
100 root_node = XMLNode()
101 if store_xml:
102 root_node.xml = xml_str
103
104 return cls.__parse_element(dom.firstChild, root_node)
105