comparison orpg/pulldom.py @ 0:4385a7d0efd1 grumpy-goblin

Deleted and repushed it with the 'grumpy-goblin' branch. I forgot a y
author sirebral
date Tue, 14 Jul 2009 16:41:58 -0500
parents
children 551cd440acce
comparison
equal deleted inserted replaced
-1:000000000000 0:4385a7d0efd1
1 import minidom
2 import xml.sax,xml.sax.handler
3 import types
4
5 try:
6 from cStringIO import StringIO
7 except ImportError:
8 from StringIO import StringIO
9
10 try:
11 _StringTypes = [types.StringType, types.UnicodeType]
12 except AttributeError:
13 _StringTypes = [types.StringType]
14
15 START_ELEMENT = "START_ELEMENT"
16 END_ELEMENT = "END_ELEMENT"
17 COMMENT = "COMMENT"
18 START_DOCUMENT = "START_DOCUMENT"
19 END_DOCUMENT = "END_DOCUMENT"
20 PROCESSING_INSTRUCTION = "PROCESSING_INSTRUCTION"
21 IGNORABLE_WHITESPACE = "IGNORABLE_WHITESPACE"
22 CHARACTERS = "CHARACTERS"
23
24 class PullDOM(xml.sax.ContentHandler):
25 def __init__(self):
26 self.firstEvent = [None, None]
27 self.lastEvent = self.firstEvent
28 self._ns_contexts = [{}] # contains uri -> prefix dicts
29 self._current_context = self._ns_contexts[-1]
30
31 def setDocumentLocator(self, locator): pass
32
33 def startPrefixMapping(self, prefix, uri):
34 self._ns_contexts.append(self._current_context.copy())
35 self._current_context[uri] = prefix
36
37 def endPrefixMapping(self, prefix):
38 del self._ns_contexts[-1]
39
40 def startElementNS(self, name, tagName , attrs):
41 uri,localname = name
42 if uri:
43 # When using namespaces, the reader may or may not
44 # provide us with the original name. If not, create
45 # *a* valid tagName from the current context.
46 if tagName is None:
47 tagName = self._current_context[uri] + ":" + localname
48 node = self.document.createElementNS(uri, tagName)
49 else:
50 # When the tagname is not prefixed, it just appears as
51 # localname
52 node = self.document.createElement(localname)
53 for aname,value in attrs.items():
54 a_uri, a_localname = aname
55 if a_uri:
56 qname = self._current_context[a_uri] + ":" + a_localname
57 attr = self.document.createAttributeNS(a_uri, qname)
58 else:
59 attr = self.document.createAttribute(a_localname)
60 attr.value = value
61 node.setAttributeNode(attr)
62 parent = self.curNode
63 node.parentNode = parent
64 self.curNode = node
65 self.lastEvent[1] = [(START_ELEMENT, node), None]
66 self.lastEvent = self.lastEvent[1]
67 #self.events.append((START_ELEMENT, node))
68
69 def endElementNS(self, name, tagName):
70 node = self.curNode
71 self.lastEvent[1] = [(END_ELEMENT, node), None]
72 self.lastEvent = self.lastEvent[1]
73 #self.events.append((END_ELEMENT, node))
74 self.curNode = node.parentNode
75
76 def startElement(self, name, attrs):
77 node = self.document.createElement(name)
78 for aname,value in attrs.items():
79 attr = self.document.createAttribute(aname)
80 attr.value = value
81 node.setAttributeNode(attr)
82 parent = self.curNode
83 node.parentNode = parent
84 self.curNode = node
85 self.lastEvent[1] = [(START_ELEMENT, node), None]
86 self.lastEvent = self.lastEvent[1]
87 #self.events.append((START_ELEMENT, node))
88
89 def endElement(self, name):
90 node = self.curNode
91 self.lastEvent[1] = [(END_ELEMENT, node), None]
92 self.lastEvent = self.lastEvent[1]
93 #self.events.append((END_ELEMENT, node))
94 self.curNode = node.parentNode
95
96 def comment(self, s):
97 node = self.document.createComment(s)
98 parent = self.curNode
99 node.parentNode = parent
100 self.lastEvent[1] = [(COMMENT, node), None]
101 self.lastEvent = self.lastEvent[1]
102 #self.events.append((COMMENT, node))
103
104 def processingInstruction(self, target, data):
105 node = self.document.createProcessingInstruction(target, data)
106 parent = self.curNode
107 node.parentNode = parent
108 self.lastEvent[1] = [(PROCESSING_INSTRUCTION, node), None]
109 self.lastEvent = self.lastEvent[1]
110 #self.events.append((PROCESSING_INSTRUCTION, node))
111
112 def ignorableWhitespace(self, chars):
113 node = self.document.createTextNode(chars[start:start + length])
114 parent = self.curNode
115 node.parentNode = parent
116 self.lastEvent[1] = [(IGNORABLE_WHITESPACE, node), None]
117 self.lastEvent = self.lastEvent[1]
118 #self.events.append((IGNORABLE_WHITESPACE, node))
119
120 def characters(self, chars):
121 node = self.document.createTextNode(chars)
122 parent = self.curNode
123 node.parentNode = parent
124 self.lastEvent[1] = [(CHARACTERS, node), None]
125 self.lastEvent = self.lastEvent[1]
126
127 def startDocument(self):
128 node = self.curNode = self.document = minidom.Document()
129 node.parentNode = None
130 self.lastEvent[1] = [(START_DOCUMENT, node), None]
131 self.lastEvent = self.lastEvent[1]
132 #self.events.append((START_DOCUMENT, node))
133
134 def endDocument(self):
135 assert not self.curNode.parentNode
136 for node in self.curNode.childNodes:
137 if node.nodeType == node.ELEMENT_NODE:
138 self.document.documentElement = node
139 #if not self.document.documentElement:
140 # raise Error, "No document element"
141 self.lastEvent[1] = [(END_DOCUMENT, node), None]
142 #self.events.append((END_DOCUMENT, self.curNode))
143
144 class ErrorHandler:
145 def warning(self, exception):
146 print exception
147 def error(self, exception):
148 raise exception
149 def fatalError(self, exception):
150 raise exception
151
152 class DOMEventStream:
153 def __init__(self, stream, parser, bufsize):
154 self.stream = stream
155 self.parser = parser
156 self.bufsize = bufsize
157 self.reset()
158
159 def reset(self):
160 self.pulldom = PullDOM()
161 # This content handler relies on namespace support
162 self.parser.setFeature(xml.sax.handler.feature_namespaces,1)
163 self.parser.setContentHandler(self.pulldom)
164
165 def __getitem__(self, pos):
166 rc = self.getEvent()
167 if rc:
168 return rc
169 raise IndexError
170
171 def expandNode(self, node):
172 event = self.getEvent()
173 while event:
174 token, cur_node = event
175 if cur_node is node:
176 return
177 if token != END_ELEMENT:
178 cur_node.parentNode.appendChild(cur_node)
179 event = self.getEvent()
180
181 def getEvent(self):
182 if not self.pulldom.firstEvent[1]:
183 self.pulldom.lastEvent = self.pulldom.firstEvent
184 while not self.pulldom.firstEvent[1]:
185 buf=self.stream.read(self.bufsize)
186 if not buf:
187 #FIXME: why doesn't Expat close work?
188 #self.parser.close()
189 return None
190 self.parser.feed(buf)
191 rc = self.pulldom.firstEvent[1][0]
192 self.pulldom.firstEvent[1] = self.pulldom.firstEvent[1][1]
193 return rc
194
195 class SAX2DOM(PullDOM):
196
197 def startElementNS(self, name, tagName , attrs):
198 PullDOM.startElementNS(self, name, tagName, attrs)
199 self.curNode.parentNode.appendChild(self.curNode)
200
201 def startElement(self, name, attrs):
202 PullDOM.startElement(self, name, attrs)
203 self.curNode.parentNode.appendChild(self.curNode)
204
205 def processingInstruction(self, target, data):
206 PullDOM.processingInstruction(self, target, data)
207 node = self.lastEvent[0][1]
208 node.parentNode.appendChild(node)
209
210 def ignorableWhitespace(self, chars):
211 PullDOM.ignorableWhitespace(self, chars)
212 node = self.lastEvent[0][1]
213 node.parentNode.appendChild(node)
214
215 def characters(self, chars):
216 PullDOM.characters(self, chars)
217 node = self.lastEvent[0][1]
218 node.parentNode.appendChild(node)
219
220 default_bufsize = (2 ** 14) - 20
221
222 def parse(stream_or_string, parser=None, bufsize=default_bufsize):
223 if type(stream_or_string) in _StringTypes:
224 stream = open(stream_or_string)
225 else:
226 stream = stream_or_string
227 if not parser:
228 parser = xml.sax.make_parser()
229 return DOMEventStream(stream, parser, bufsize)
230
231 def parseString(string, parser=None):
232 bufsize = len(string)
233 buf = StringIO(string)
234 if not parser:
235 parser = xml.sax.make_parser()
236 return DOMEventStream(buf, parser, bufsize)