| Home | Trees | Indices | Help |
|
|---|
|
|
1 # Copyright 2009, Peter A. Bigot
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain a
5 # copy of the License at:
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 """This module contains support for a DOM tree representation from an XML
16 document using a SAX parser.
17
18 This functionality exists because we need a DOM interface to generate the
19 binding classses, but the Python C{xml.dom.minidom} package does not support
20 location information. The SAX interface does, so we have a SAX content
21 handler which converts the SAX events into a DOM tree.
22
23 This is not a general-purpose DOM capability; only a small subset of the DOM
24 interface is supported, and only for storing the XML information, not for
25 converting it back into document format.
26 """
27
28 import xml.dom
29 import saxutils
30 import StringIO
31 import pyxb.namespace
32
34 """Utility function to print a DOM tree."""
35
36 pfx = ' ' * depth
37 if (xml.dom.Node.ELEMENT_NODE == n.nodeType):
38 print '%sElement[%d] %s %s with %d children' % (pfx, n._indexInParent(), n, pyxb.namespace.ExpandedName(n.name), len(n.childNodes))
39 ins = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(n).inScopeNamespaces()
40 print '%s%s' % (pfx, ' ; '.join([ '%s=%s' % (_k, _v.uri()) for (_k, _v) in ins.items()]))
41 for (k, v) in n.attributes.items():
42 print '%s %s=%s' % (pfx, pyxb.namespace.ExpandedName(k), v)
43 for cn in n.childNodes:
44 _DumpDOM(cn, depth+1)
45 elif (xml.dom.Node.TEXT_NODE == n.nodeType):
46 #print '%sText "%s"' % (pfx, n.value)
47 pass
48 elif (xml.dom.Node.DOCUMENT_NODE == n.nodeType):
49 print 'Document node'
50 _DumpDOM(n.firstChild, depth)
51 else:
52 print 'UNRECOGNIZED %s' % (n.nodeType,)
53
55 """SAX handler class that transforms events into a DOM tree."""
56
60 __document = None
61
63 super(_DOMSAXHandler, self).startDocument()
64 self.__document = Document(namespace_context=self.namespaceContext())
65
67 content = self.elementState().content()
68 if 0 < len(content):
69 ( content, element_use, maybe_element ) = content[0]
70 self.__document.appendChild(content)
71 #_DumpDOM(content)
72
74 (this_state, parent_state, ns_ctx, name_en) = super(_DOMSAXHandler, self).startElementNS(name, qname, attrs)
75 this_state.__attributes = NamedNodeMap()
76 for name in attrs.getNames():
77 attr_en = pyxb.namespace.ExpandedName(name)
78 value = attrs.getValue(name)
79 this_state.__attributes._addItem(Attr(expanded_name=attr_en, namespace_context=ns_ctx, value=value, location=this_state.location()))
80
82 this_state = super(_DOMSAXHandler, self).endElementNS(name, qname)
83 ns_ctx = this_state.namespaceContext()
84 element = Element(namespace_context=ns_ctx, expanded_name=this_state.expandedName(), attributes=this_state.__attributes, location=this_state.location())
85 for ( content, element_use, maybe_element ) in this_state.content():
86 if isinstance(content, Node):
87 element.appendChild(content)
88 else:
89 element.appendChild(Text(content, namespace_context=ns_ctx))
90 parent_state = this_state.parentState()
91 parent_state.addElementContent(element, None)
92 #print '%s %s has %d children' % (element.namespaceURI, element.localName, len(element.childNodes))
93
95 """Parse a stream containing an XML document and return the DOM tree
96 representing its contents.
97
98 Keywords not described here are passed to L{saxutils.make_parser}.
99
100 @param stream: An object presenting the standard file C{read} interface
101 from which the document can be read.
102
103 @keyword content_handler_constructor: Input is overridden to assign this a
104 value of L{_DOMSAXHandler}.
105
106 @rtype: C{xml.dom.Document}
107 """
108
109 kw['content_handler_constructor'] = _DOMSAXHandler
110 saxer = saxutils.make_parser(**kw)
111 handler = saxer.getContentHandler()
112 saxer.parse(stream)
113 return handler.document()
114
116 """Parse a string holding an XML document and return the corresponding DOM
117 tree."""
118
119 return parse(StringIO.StringIO(text), **kw)
120
122 """Base for the minimal DOM interface required by PyXB."""
124 location = kw.pop('location', None)
125 if location is not None:
126 pyxb.utils.utility.Locatable_mixin.__init__(self, location=location)
127 self.__nodeType = node_type
128 self.__parentNode = None
129 self.__childNodes = []
130 self.__namespaceContext = kw['namespace_context']
131 self.__value = kw.get('value')
132 self.__attributes = kw.get('attributes')
133 expanded_name = kw.get('expanded_name')
134 if expanded_name is not None:
135 self.__name = expanded_name.uriTuple()
136 self.__namespaceURI = expanded_name.namespaceURI()
137 self.__localName = expanded_name.localName()
138 self.__namespaceContext.setNodeContext(self)
139
140 location = property(lambda _s: _s._location())
141
142 __name = None
143 name = property(lambda _s: _s.__name)
145 __namespaceURI = None
146 namespaceURI = property(lambda _s: _s.__namespaceURI)
147 __localName = None
148 localName = property(lambda _s: _s.__localName)
149 __value = None
150 value = property(lambda _s: _s.__value)
151
153
158
162
166
170 __attributes = None
171
172 nodeType = property(lambda _s: _s.__nodeType)
173 parentNode = property(lambda _s: _s.__parentNode)
174 firstChild = property(lambda _s: _s.__childIfPresent(0))
175 childNodes = property(lambda _s: _s.__childNodes)
176 attributes = property(lambda _s: _s.__attributes)
177
178 nextSibling = property(lambda _s: _s.parentNode.__childIfPresent(_s.__indexInParent+1))
179
181 return self.getAttributeNodeNS(ns_uri, local_name) is not None
182
185
187 rv = self.getAttributeNodeNS(ns_uri, local_name)
188 if rv is None:
189 return ''
190 return rv.value
191
198
200 """Add the nodeName and nodeValue interface."""
203 nodeName = Node.name
204 nodeValue = Node.value
205
207 """Implement that portion of NamedNodeMap required to satisfy PyXB's
208 needs."""
209 __members = None
210
214
215 length = property(lambda _s: len(_s.__members))
218
220 self[attr.name] = attr.value
221 assert pyxb.namespace.resolution.NamespaceContext.GetNodeContext(attr) is not None
222 self.__members.append(attr)
223
229
232 super(Element, self).__init__(node_type=xml.dom.Node.ELEMENT_NODE, **kw)
233 assert self.attributes is not None
234 nodeName = Node.localName
235
239
243
247
248 if '__main__' == __name__:
249 import sys
250 xml_file = '/home/pab/pyxb/dev/examples/tmsxtvd/tmsdatadirect_sample.xml'
251 if 1 < len(sys.argv):
252 xml_file = sys.argv[1]
253
254 doc = parse(file(xml_file))
255
256 ## Local Variables:
257 ## fill-column:78
258 ## End:
259
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sat Nov 7 20:11:56 2009 | http://epydoc.sourceforge.net |