1
2
3
4
5
6
7
8
9
10
11
12
13
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
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
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
58 """The document that is the root of the generated tree."""
59 return self.__document
60 __document = None
61
65
71
72
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
93
94 -def parse (stream, **kw):
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 if isinstance(text, unicode):
120 text = text.encode(pyxb._InputEncoding)
121 return parse(StringIO.StringIO(text), **kw)
122
123 -class Node (xml.dom.Node, pyxb.utils.utility.Locatable_mixin):
197
199 """Add the documentElement interface."""
202
203 documentElement = Node.firstChild
204
206 """Add the nodeName and nodeValue interface."""
209 nodeName = Node.name
210 nodeValue = Node.value
211
213 """Implement that portion of NamedNodeMap required to satisfy PyXB's
214 needs."""
215 __members = None
216
220
221 length = property(lambda _s: len(_s.__members))
222 - def item (self, index):
224
229
231 for attr in self.__members:
232 if attr.name == name:
233 return attr
234 return None
235
242
244 """Abstract base for anything holding text data."""
245 data = Node.value
246
247 -class Text (_CharacterData):
248 - def __init__ (self, text, **kw):
249 super(Text, self).__init__(value=text, node_type=xml.dom.Node.TEXT_NODE, **kw)
250
254
255 if '__main__' == __name__:
256 import sys
257 xml_file = 'examples/tmsxtvd/tmsdatadirect_sample.xml'
258 if 1 < len(sys.argv):
259 xml_file = sys.argv[1]
260
261 doc = parse(file(xml_file))
262
263
264
265
266