root/tags/Release-0_3_2/RBFoundation/RBFoundation/ObjectifiedXMLParser.py

Revision 253, 5.2 kB (checked in by sholloway, 6 years ago)

Changed to BSD License

Line 
1 #!/usr/bin/env python
2 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 ##~ License
4 ##~
5 ##- The RuneBlade Foundation library is intended to ease some
6 ##- aspects of writing intricate Jabber, XML, and User Interface (wxPython, etc.)
7 ##- applications, while providing the flexibility to modularly change the
8 ##- architecture. Enjoy.
9 ##~
10 ##~ Copyright (C) 2002  TechGame Networks, LLC.
11 ##~
12 ##~ This library is free software; you can redistribute it and/or
13 ##~ modify it under the terms of the BSD style License as found in the
14 ##~ LICENSE file included with this distribution.
15 ##~
16 ##~ TechGame Networks, LLC can be reached at:
17 ##~ 3578 E. Hartsel Drive #211
18 ##~ Colorado Springs, Colorado, USA, 80920
19 ##~
20 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21
22 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 #~ Imports
24 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25
26 from xml.parsers.expat import ParserCreate as _ParserCreate
27 from WeakBind import BindCallable
28
29 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30 #~ Definitions
31 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32
33 class LazyExpatXMLParser(object):
34     """Use Expat parser to parse string/file data, but create the
35     parser as late as possible."""
36     def __init__(self, encoding='ASCII', seperator=' '):
37         self._encoding = encoding
38         self._seperator = seperator
39
40     def Parse(self, *args, **kw):
41         # Ok, use the standard expat parser...
42         parser = _ParserCreate(self._encoding, self._seperator)
43         parser.returns_unicode = self._encoding != 'ASCII' and 1 or 0
44         parser.StartElementHandler = BindCallable(self.StartElementHandler)
45         parser.EndElementHandler = BindCallable(self.EndElementHandler)
46         parser.CharacterDataHandler = BindCallable(self.CharacterDataHandler)
47         parser.StartNamespaceDeclHandler = BindCallable(self.StartNamespaceDeclHandler)
48         parser.EndNamespaceDeclHandler = BindCallable(self.EndNamespaceDeclHandler)
49         return parser.Parse(*args, **kw)
50
51     def ParseFile(self, *args, **kw):
52         # Ok, use the standard expat parser...
53         parser = _ParserCreate(self._encoding, self._seperator)
54         parser.returns_unicode = self._encoding != 'ASCII' and 1 or 0
55         parser.StartElementHandler = BindCallable(self.StartElementHandler)
56         parser.EndElementHandler = BindCallable(self.EndElementHandler)
57         parser.CharacterDataHandler = BindCallable(self.CharacterDataHandler)
58         parser.StartNamespaceDeclHandler = BindCallable(self.StartNamespaceDeclHandler)
59         parser.EndNamespaceDeclHandler = BindCallable(self.EndNamespaceDeclHandler)
60         return parser.ParseFile(*args, **kw)
61
62 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
63
64 class ObjectifiedXMLParser(LazyExpatXMLParser):
65     """Mimics the events of the Expat parser with an Objectifed XML
66     object as the source data.  Builds on LazyExpatXMLParser in case
67     the passed in data is in string form."""
68     def Parse(self, obj, *args, **kw):
69         if not isinstance(obj, str):
70             # Here's the magic... reuse the already objectified XML
71             for uri, prefix in obj.__namespace_map__.iteritems():
72                 self.StartNamespaceDeclHandler(prefix, uri)
73             name = self._seperator.join([obj.__namespace__, obj.__node__])
74             self.StartElementHandler(name, obj._attributes)
75             for each in obj._elements:
76                 if each[0][-1]: self.Parse(each[-1])
77                 else: self.CharacterDataHandler(each[-1])
78             result = self.EndElementHandler(name)
79             for prefix in obj.__namespace_map__.itervalues():
80                 self.EndNamespaceDeclHandler(prefix, uri)
81             return result
82         else:
83             return super(ObjectifiedXMLParser, self).Parse(obj, *args, **kw)
84
85 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
86 #~ Testing                                           
87 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
88
89 def _Test_XMLObjectify():
90     from XMLObjectify import Objectifier
91     xmlfile = open('test_objectify.xml', 'r')
92     maker = Objectifier()
93     maker.SetParserFactory(ObjectifiedXMLParser)
94
95     objFile = maker.ObjectifyFile(xmlfile)
96     xmlfile.seek(0)
97     objString = maker.Objectify(xmlfile.read())
98
99     assert objFile == objString
100
101     objObjecitfied1 = maker.Objectify(objFile)
102     objObjecitfied2 = maker.Objectify(objString)
103     objObjecitfied3 = maker.Objectify(objObjecitfied1)
104     objObjecitfied4 = maker.Objectify(objObjecitfied2)
105
106     assert objFile == objObjecitfied1
107     assert objString == objObjecitfied1
108     assert objFile == objObjecitfied2
109     assert objString == objObjecitfied2
110     assert objFile == objObjecitfied3
111     assert objString == objObjecitfied3
112     assert objFile == objObjecitfied4
113     assert objString == objObjecitfied4
114
115     assert objObjecitfied1 == objObjecitfied2
116     assert objObjecitfied1 == objObjecitfied3
117     assert objObjecitfied1 == objObjecitfied4
118     assert objObjecitfied2 == objObjecitfied3
119     assert objObjecitfied2 == objObjecitfied4
120     assert objObjecitfied3 == objObjecitfied4
121
122 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
123
124 if __name__=='__main__':
125     print "Testing..."
126     _Test_XMLObjectify()
127     print "Test complete."
128
Note: See TracBrowser for help on using the browser.