1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 import xml.dom
30 import pyxb.utils.saxutils
31 import StringIO
32 import pyxb.namespace
33 import logging
34
35 _log = logging.getLogger(__name__)
38 """Utility function to print a DOM tree."""
39
40 pfx = ' ' * depth
41 if (xml.dom.Node.ELEMENT_NODE == n.nodeType):
42 print '%sElement[%d] %s %s with %d children' % (pfx, n._indexInParent(), n, pyxb.namespace.ExpandedName(n.name), len(n.childNodes))
43 ins = pyxb.namespace.resolution.NamespaceContext.GetNodeContext(n).inScopeNamespaces()
44 print '%s%s' % (pfx, ' ; '.join([ '%s=%s' % (_k, _v.uri()) for (_k, _v) in ins.items()]))
45 for (k, v) in n.attributes.items():
46 print '%s %s=%s' % (pfx, pyxb.namespace.ExpandedName(k), v)
47 for cn in n.childNodes:
48 _DumpDOM(cn, depth+1)
49 elif (xml.dom.Node.TEXT_NODE == n.nodeType):
50
51 pass
52 elif (xml.dom.Node.DOCUMENT_NODE == n.nodeType):
53 print 'Document node'
54 _DumpDOM(n.firstChild, depth)
55 else:
56 print 'UNRECOGNIZED %s' % (n.nodeType,)
57
59 """SAX handler class that transforms events into a DOM tree."""
60
62 """The document that is the root of the generated tree."""
63 return self.__document
64 __document = None
65
69
75
76
84
86 this_state = super(_DOMSAXHandler, self).endElementNS(name, qname)
87 ns_ctx = this_state.namespaceContext()
88 element = Element(namespace_context=ns_ctx, expanded_name=this_state.expandedName(), attributes=this_state.__attributes, location=this_state.location())
89 for ( content, element_use, maybe_element ) in this_state.content():
90 if isinstance(content, Node):
91 element.appendChild(content)
92 else:
93 element.appendChild(Text(content, namespace_context=ns_ctx))
94 parent_state = this_state.parentState()
95 parent_state.addElementContent(element, None)
96
98 """Parse a stream containing an XML document and return the DOM tree
99 representing its contents.
100
101 Keywords not described here are passed to L{pyxb.utils.saxutils.make_parser}.
102
103 @param stream: An object presenting the standard file C{read} interface
104 from which the document can be read.
105
106 @keyword content_handler_constructor: Input is overridden to assign this a
107 value of L{_DOMSAXHandler}.
108
109 @rtype: C{xml.dom.Document}
110 """
111
112 kw['content_handler_constructor'] = _DOMSAXHandler
113 saxer = pyxb.utils.saxutils.make_parser(**kw)
114 handler = saxer.getContentHandler()
115 saxer.parse(stream)
116 return handler.document()
117
125
126 -class Node (xml.dom.Node, pyxb.utils.utility.Locatable_mixin):
201
203 """Add the documentElement interface."""
206
207 documentElement = Node.firstChild
208
210 """Add the nodeName and nodeValue interface."""
213 nodeName = Node.name
214 nodeValue = Node.value
215
217 """Implement that portion of NamedNodeMap required to satisfy PyXB's
218 needs."""
219 __members = None
220
224
225 length = property(lambda _s: len(_s.__members))
226 - def item (self, index):
228
233
235 for attr in self.__members:
236 if attr.name == name:
237 return attr
238 return None
239
246
248 """Abstract base for anything holding text data."""
249 data = Node.value
250
251 -class Text (_CharacterData):
252 - def __init__ (self, text, **kw):
253 super(Text, self).__init__(value=text, node_type=xml.dom.Node.TEXT_NODE, **kw)
254
258
259 if '__main__' == __name__:
260 import sys
261 xml_file = 'examples/tmsxtvd/tmsdatadirect_sample.xml'
262 if 1 < len(sys.argv):
263 xml_file = sys.argv[1]
264
265 doc = parse(file(xml_file))
266
267
268
269
270