| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: utf-8 -*-
2 # Copyright 2009-2013, Peter A. Bigot
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain a
6 # copy of the License at:
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15
16 """This module contains support for a DOM tree representation from an XML
17 document using a SAX parser.
18
19 This functionality exists because we need a DOM interface to generate the
20 binding classses, but the Python C{xml.dom.minidom} package does not support
21 location information. The SAX interface does, so we have a SAX content
22 handler which converts the SAX events into a DOM tree.
23
24 This is not a general-purpose DOM capability; only a small subset of the DOM
25 interface is supported, and only for storing the XML information, not for
26 converting it back into document format.
27 """
28
29 from __future__ import print_function
30 import xml.dom
31 import pyxb.utils.saxutils
32 import pyxb.utils.types_
33 import io
34 import pyxb.namespace
35 import logging
36
37 _log = logging.getLogger(__name__)
38
40 """Utility function to print a DOM tree."""
41
42 pfx = ' ' * depth
43 if (xml.dom.Node.ELEMENT_NODE == n.nodeType):
44 print('%sElement[%d] %s %s with %d children' % (pfx, n._indexInParent(), n, pyxb.namespace.ExpandedName(n.name), len(n.childNodes)))
45 ins = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(n).inScopeNamespaces()
46 print('%s%s' % (pfx, ' ; '.join([ '%s=%s' % (_k, _v.uri()) for (_k, _v) in ins.items()])))
47 for (k, v) in n.attributes.iteritems():
48 print('%s %s=%s' % (pfx, pyxb.namespace.ExpandedName(k), v))
49 for cn in n.childNodes:
50 _DumpDOM(cn, depth+1)
51 elif (xml.dom.Node.TEXT_NODE == n.nodeType):
52 #print '%sText "%s"' % (pfx, n.value)
53 pass
54 elif (xml.dom.Node.DOCUMENT_NODE == n.nodeType):
55 print('Document node')
56 _DumpDOM(n.firstChild, depth)
57 else:
58 print('UNRECOGNIZED %s' % (n.nodeType,))
59
61 """SAX handler class that transforms events into a DOM tree."""
62
66 __document = None
67
69 super(_DOMSAXHandler, self).startDocument()
70 self.__document = Document(namespace_context=self.namespaceContext())
71
73 content = self.elementState().content()
74 if 0 < len(content):
75 assert content[0].maybe_element
76 self.__document.appendChild(content[0].item)
77 #_DumpDOM(content)
78
80 (this_state, parent_state, ns_ctx, name_en) = super(_DOMSAXHandler, self).startElementNS(name, qname, attrs)
81 this_state.__attributes = NamedNodeMap()
82 for name in attrs.getNames():
83 attr_en = pyxb.namespace.ExpandedName(name)
84 value = attrs.getValue(name)
85 this_state.__attributes._addItem(Attr(expanded_name=attr_en, namespace_context=ns_ctx, value=value, location=this_state.location()))
86
88 this_state = super(_DOMSAXHandler, self).endElementNS(name, qname)
89 ns_ctx = this_state.namespaceContext()
90 element = Element(namespace_context=ns_ctx, expanded_name=this_state.expandedName(), attributes=this_state.__attributes, location=this_state.location())
91 for info in this_state.content():
92 if isinstance(info.item, Node):
93 element.appendChild(info.item)
94 else:
95 element.appendChild(Text(info.item, namespace_context=ns_ctx))
96 parent_state = this_state.parentState()
97 parent_state.addElementContent(this_state.location(), element, None)
98
100 """Parse a stream containing an XML document and return the DOM tree
101 representing its contents.
102
103 Keywords not described here are passed to L{pyxb.utils.saxutils.make_parser}.
104
105 @param stream: An object presenting the standard file C{read} interface
106 from which the document can be read. The content should be data, not text.
107
108 @keyword content_handler_constructor: Input is overridden to assign this a
109 value of L{_DOMSAXHandler}.
110
111 @rtype: C{xml.dom.Document}
112 """
113
114 kw['content_handler_constructor'] = _DOMSAXHandler
115 saxer = pyxb.utils.saxutils.make_parser(**kw)
116 handler = saxer.getContentHandler()
117 saxer.parse(stream)
118 return handler.document()
119
121 """Parse a string holding an XML document and return the corresponding DOM
122 tree.
123
124 @param xml_text: the XML content to be parsed, in a text representation."""
125 # SAX parser operates on data, not text.
126 xmld = xml_text
127 if isinstance(xmld, pyxb.utils.types_.TextType):
128 xmld = xmld.encode(pyxb._InputEncoding)
129 return parse(io.BytesIO(xmld), **kw)
130
132 """Base for the minimal DOM interface required by PyXB."""
134 location = kw.pop('location', None)
135 if location is not None:
136 pyxb.utils.utility.Locatable_mixin.__init__(self, location=location)
137 self.__nodeType = node_type
138 self.__parentNode = None
139 self.__indexInParent = None
140 self.__childNodes = []
141 self.__namespaceContext = kw['namespace_context']
142 self.__value = kw.get('value')
143 self.__attributes = kw.get('attributes')
144 en = kw.get('expanded_name')
145 if en is not None:
146 self.__expandedName = en
147 ns = en.namespace()
148 if (ns is not None) and not (ns.prefix() is None):
149 assert not ns.isAbsentNamespace()
150 self.__prefix = ns.prefix()
151 if (ns is not None):
152 self.__namespaceURI = ns.uri()
153 self.__localName = en.localName()
154 if self.__prefix:
155 self.__tagName = '%s:%s' % (self.__prefix, self.__localName)
156 else:
157 self.__tagName = self.__localName
158 self.__namespaceContext.setNodeContext(self)
159
160 location = property(lambda _s: _s._location())
161
162 __expandedName = None
163 _expandedName = property(lambda _s: _s.__expandedName)
164 __prefix = ''
165 prefix = property(lambda _s: _s.__prefix)
166 __tagName = ''
167 tagName = property(lambda _s: _s.__tagName)
168 __namespaceURI = None
169 namespaceURI = property(lambda _s: _s.__namespaceURI)
170 __localName = None
171 localName = property(lambda _s: _s.__localName)
172 __value = None
173 value = property(lambda _s: _s.__value)
174
176
181
185
189
193 __attributes = None
194
195 nodeType = property(lambda _s: _s.__nodeType)
196 parentNode = property(lambda _s: _s.__parentNode)
197 firstChild = property(lambda _s: _s.__childIfPresent(0))
198 childNodes = property(lambda _s: _s.__childNodes)
199 attributes = property(lambda _s: _s.__attributes)
200
201 nextSibling = property(lambda _s: _s.parentNode.__childIfPresent(_s.__indexInParent+1))
202
204 return self.getAttributeNodeNS(ns_uri, local_name) is not None
205
208
210 rv = self.getAttributeNodeNS(ns_uri, local_name)
211 if rv is None:
212 return ''
213 return rv.value
214
221
223 """Add the nodeName and nodeValue interface."""
226 name = Node.tagName
227 nodeName = Node.tagName
228 nodeValue = Node.value
229
231 """Implement that portion of NamedNodeMap required to satisfy PyXB's
232 needs."""
233 __members = None
234 __memberMap = None
235
240
241 length = property(lambda _s: len(_s.__members))
244
246 assert pyxb.namespace.resolution.NamespaceContext.GetNodeContext(attr) is not None
247 self.__members.append(attr)
248 en = attr._expandedName
249 if en is not None:
250 self.__memberMap[en] = attr
251
257
260 super(Element, self).__init__(node_type=xml.dom.Node.ELEMENT_NODE, **kw)
261 assert self.attributes is not None
262 tagName = Node.localName
263 nodeName = Node.localName
264
268
272
276
277 if '__main__' == __name__:
278 import sys
279 xml_file = 'examples/tmsxtvd/tmsdatadirect_sample.xml'
280 if 1 < len(sys.argv):
281 xml_file = sys.argv[1]
282
283 doc = parse(open(xml_file))
284
285 ## Local Variables:
286 ## fill-column:78
287 ## End:
288
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Wed Sep 18 10:35:41 2013 | http://epydoc.sourceforge.net |