]> git.saurik.com Git - wxWidgets.git/blob - wxPython/samples/stxview/StructuredText/STDOM.py
Got a new version of StructuredText from Zope's CVS.
[wxWidgets.git] / wxPython / samples / stxview / StructuredText / STDOM.py
1 ##############################################################################
2 #
3 # Zope Public License (ZPL) Version 1.0
4 # -------------------------------------
5 #
6 # Copyright (c) Digital Creations. All rights reserved.
7 #
8 # This license has been certified as Open Source(tm).
9 #
10 # Redistribution and use in source and binary forms, with or without
11 # modification, are permitted provided that the following conditions are
12 # met:
13 #
14 # 1. Redistributions in source code must retain the above copyright
15 # notice, this list of conditions, and the following disclaimer.
16 #
17 # 2. Redistributions in binary form must reproduce the above copyright
18 # notice, this list of conditions, and the following disclaimer in
19 # the documentation and/or other materials provided with the
20 # distribution.
21 #
22 # 3. Digital Creations requests that attribution be given to Zope
23 # in any manner possible. Zope includes a "Powered by Zope"
24 # button that is installed by default. While it is not a license
25 # violation to remove this button, it is requested that the
26 # attribution remain. A significant investment has been put
27 # into Zope, and this effort will continue if the Zope community
28 # continues to grow. This is one way to assure that growth.
29 #
30 # 4. All advertising materials and documentation mentioning
31 # features derived from or use of this software must display
32 # the following acknowledgement:
33 #
34 # "This product includes software developed by Digital Creations
35 # for use in the Z Object Publishing Environment
36 # (http://www.zope.org/)."
37 #
38 # In the event that the product being advertised includes an
39 # intact Zope distribution (with copyright and license included)
40 # then this clause is waived.
41 #
42 # 5. Names associated with Zope or Digital Creations must not be used to
43 # endorse or promote products derived from this software without
44 # prior written permission from Digital Creations.
45 #
46 # 6. Modified redistributions of any form whatsoever must retain
47 # the following acknowledgment:
48 #
49 # "This product includes software developed by Digital Creations
50 # for use in the Z Object Publishing Environment
51 # (http://www.zope.org/)."
52 #
53 # Intact (re-)distributions of any official Zope release do not
54 # require an external acknowledgement.
55 #
56 # 7. Modifications are encouraged but must be packaged separately as
57 # patches to official Zope releases. Distributions that do not
58 # clearly separate the patches from the original work must be clearly
59 # labeled as unofficial distributions. Modifications which do not
60 # carry the name Zope may be packaged in any form, as long as they
61 # conform to all of the clauses above.
62 #
63 #
64 # Disclaimer
65 #
66 # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
67 # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
69 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
70 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
71 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
72 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
73 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
74 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
75 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
76 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
77 # SUCH DAMAGE.
78 #
79 #
80 # This software consists of contributions made by Digital Creations and
81 # many individuals on behalf of Digital Creations. Specific
82 # attributions are listed in the accompanying credits file.
83 #
84 ##############################################################################
85 """
86 DOM implementation in StructuredText : Read-Only methods
87
88 All standard Zope objects support DOM to a limited extent.
89 """
90 import string
91
92
93 # Node type codes
94 # ---------------
95
96 ELEMENT_NODE = 1
97 ATTRIBUTE_NODE = 2
98 TEXT_NODE = 3
99 CDATA_SECTION_NODE = 4
100 ENTITY_REFERENCE_NODE = 5
101 ENTITY_NODE = 6
102 PROCESSING_INSTRUCTION_NODE = 7
103 COMMENT_NODE = 8
104 DOCUMENT_NODE = 9
105 DOCUMENT_TYPE_NODE = 10
106 DOCUMENT_FRAGMENT_NODE = 11
107 NOTATION_NODE = 12
108
109 # Exception codes
110 # ---------------
111
112 INDEX_SIZE_ERR = 1
113 DOMSTRING_SIZE_ERR = 2
114 HIERARCHY_REQUEST_ERR = 3
115 WRONG_DOCUMENT_ERR = 4
116 INVALID_CHARACTER_ERR = 5
117 NO_DATA_ALLOWED_ERR = 6
118 NO_MODIFICATION_ALLOWED_ERR = 7
119 NOT_FOUND_ERR = 8
120 NOT_SUPPORTED_ERR = 9
121 INUSE_ATTRIBUTE_ERR = 10
122
123 # Exceptions
124 # ----------
125
126 class DOMException(Exception):
127 pass
128 class IndexSizeException(DOMException):
129 code = INDEX_SIZE_ERR
130 class DOMStringSizeException(DOMException):
131 code = DOMSTRING_SIZE_ERR
132 class HierarchyRequestException(DOMException):
133 code = HIERARCHY_REQUEST_ERR
134 class WrongDocumentException(DOMException):
135 code = WRONG_DOCUMENT_ERR
136 class InvalidCharacterException(DOMException):
137 code = INVALID_CHARACTER_ERR
138 class NoDataAllowedException(DOMException):
139 code = NO_DATA_ALLOWED_ERR
140 class NoModificationAllowedException(DOMException):
141 code = NO_MODIFICATION_ALLOWED_ERR
142 class NotFoundException(DOMException):
143 code = NOT_FOUND_ERR
144 class NotSupportedException(DOMException):
145 code = NOT_SUPPORTED_ERR
146 class InUseAttributeException(DOMException):
147 code = INUSE_ATTRIBUTE_ERR
148
149 # Node classes
150 # ------------
151
152 class ParentNode:
153 """
154 A node that can have children, or, more precisely, that implements
155 the child access methods of the DOM.
156 """
157
158 def getChildNodes(self, type=type, st=type('')):
159 """
160 Returns a NodeList that contains all children of this node.
161 If there are no children, this is a empty NodeList
162 """
163
164 r=[]
165 for n in self.getChildren():
166 if type(n) is st: n=TextNode(n)
167 r.append(n.__of__(self))
168
169 return NodeList(r)
170
171 def getFirstChild(self, type=type, st=type('')):
172 """
173 The first child of this node. If there is no such node
174 this returns None
175 """
176 children = self.getChildren()
177
178 if not children:
179 return None
180
181 n=children[0]
182
183 if type(n) is st:
184 n=TextNode(n)
185
186 return n.__of__(self)
187
188 def getLastChild(self, type=type, st=type('')):
189 """
190 The last child of this node. If there is no such node
191 this returns None.
192 """
193 children = self.getChildren()
194 if not children: return None
195 n=chidren[-1]
196 if type(n) is st: n=TextNode(n)
197 return n.__of__(self)
198
199 """
200 create aliases for all above functions in the pythony way.
201 """
202
203 def _get_ChildNodes(self, type=type, st=type('')):
204 return self.getChildNodes(type,st)
205
206 def _get_FirstChild(self, type=type, st=type('')):
207 return self.getFirstChild(type,st)
208
209 def _get_LastChild(self, type=type, st=type('')):
210 return self.getLastChild(type,st)
211
212 class NodeWrapper(ParentNode):
213 """
214 This is an acquisition-like wrapper that provides parent access for
215 DOM sans circular references!
216 """
217
218 def __init__(self, aq_self, aq_parent):
219 self.aq_self=aq_self
220 self.aq_parent=aq_parent
221
222 def __getattr__(self, name):
223 return getattr(self.aq_self, name)
224
225 def getParentNode(self):
226 """
227 The parent of this node. All nodes except Document
228 DocumentFragment and Attr may have a parent
229 """
230 return self.aq_parent
231
232 def _getDOMIndex(self, children, getattr=getattr):
233 i=0
234 self=self.aq_self
235 for child in children:
236 if getattr(child, 'aq_self', child) is self:
237 self._DOMIndex=i
238 return i
239 i=i+1
240 return None
241
242 def getPreviousSibling(self,
243 type=type,
244 st=type(''),
245 getattr=getattr,
246 None=None):
247
248 """
249 The node immediately preceding this node. If
250 there is no such node, this returns None.
251 """
252
253 children = self.aq_parent.getChildren()
254 if not children:
255 return None
256
257 index=getattr(self, '_DOMIndex', None)
258 if index is None:
259 index=self._getDOMIndex(children)
260 if index is None: return None
261
262 index=index-1
263 if index < 0: return None
264 try: n=children[index]
265 except IndexError: return None
266 else:
267 if type(n) is st:
268 n=TextNode(n)
269 n._DOMIndex=index
270 return n.__of__(self)
271
272
273 def getNextSibling(self, type=type, st=type('')):
274 """
275 The node immediately preceding this node. If
276 there is no such node, this returns None.
277 """
278 children = self.aq_parent.getChildren()
279 if not children:
280 return None
281
282 index=getattr(self, '_DOMIndex', None)
283 if index is None:
284 index=self._getDOMIndex(children)
285 if index is None:
286 return None
287
288 index=index+1
289 try: n=children[index]
290 except IndexError:
291 return None
292 else:
293 if type(n) is st:
294 n=TextNode(n)
295 n._DOMIndex=index
296 return n.__of__(self)
297
298 def getOwnerDocument(self):
299 """
300 The Document object associated with this node, if any.
301 """
302 return self.aq_parent.getOwnerDocument()
303
304 """
305 create aliases for all above functions in the pythony way.
306 """
307
308 def _get_ParentNode(self):
309 return self.getParentNode()
310
311 def _get_DOMIndex(self, children, getattr=getattr):
312 return self._getDOMIndex(children,getattr)
313
314 def _get_PreviousSibling(self,
315 type=type,
316 st=type(''),
317 getattr=getattr,
318 None=None):
319
320 return self.getPreviousSibling(type,st,getattr,None)
321
322 def _get_NextSibling(self, type=type, st=type('')):
323 return self.getNextSibling(type,st)
324
325 def _get_OwnerDocument(self):
326 return self.getOwnerDocument()
327
328 class Node(ParentNode):
329 """
330 Node Interface
331 """
332
333 # Get a DOM wrapper with a parent link
334 def __of__(self, parent):
335 return NodeWrapper(self, parent)
336
337 # DOM attributes
338 # --------------
339
340 def getNodeName(self):
341 """
342 The name of this node, depending on its type
343 """
344
345 def getNodeValue(self):
346 """
347 The value of this node, depending on its type
348 """
349 return None
350
351 def getParentNode(self):
352 """
353 The parent of this node. All nodes except Document
354 DocumentFragment and Attr may have a parent
355 """
356
357 def getChildren(self):
358 """
359 Get a Python sequence of children
360 """
361 return ()
362
363 def getPreviousSibling(self,
364 type=type,
365 st=type(''),
366 getattr=getattr,
367 None=None):
368 """
369 The node immediately preceding this node. If
370 there is no such node, this returns None.
371 """
372
373 def getNextSibling(self, type=type, st=type('')):
374 """
375 The node immediately preceding this node. If
376 there is no such node, this returns None.
377 """
378
379 def getAttributes(self):
380 """
381 Returns a NamedNodeMap containing the attributes
382 of this node (if it is an element) or None otherwise.
383 """
384 return None
385
386 def getOwnerDocument(self):
387 """
388 The Document object associated with this node, if any.
389 """
390
391 # DOM Methods
392 # -----------
393
394 def hasChildNodes(self):
395 """
396 Returns true if the node has any children, false
397 if it doesn't.
398 """
399 return len(self.getChildren())
400
401 """
402 create aliases for all above functions in the pythony way.
403 """
404
405 def _get_NodeName(self):
406 return self.getNodeName()
407
408 def _get_NodeValue(self):
409 return self.getNodeValue()
410
411 def _get_ParentNode(self):
412 return self.getParentNode()
413
414 def _get_Children(self):
415 return self.getChildren()
416
417 def _get_PreviousSibling(self,
418 type=type,
419 st=type(''),
420 getattr=getattr,
421 None=None):
422
423 return self.getPreviousSibling(type,st,getattr,None)
424
425 def _get_NextSibling(self, type=type, st=type('')):
426 return self.getNextSibling()
427
428 def _get_Attributes(self):
429 return self.getAttributes()
430
431 def _get_OwnerDocument(self):
432 return self.getOwnerDocument()
433
434 def _has_ChildNodes(self):
435 return self.hasChildNodes()
436
437
438 class TextNode(Node):
439
440 def __init__(self, str): self._value=str
441
442 def getNodeType(self):
443 return TEXT_NODE
444
445 def getNodeName(self):
446 return '#text'
447
448 def getNodeValue(self):
449 return self._value
450
451 """
452 create aliases for all above functions in the pythony way.
453 """
454
455 def _get_NodeType(self):
456 return self.getNodeType()
457
458 def _get_NodeName(self):
459 return self.getNodeName()
460
461 def _get_NodeValue(self):
462 return self.getNodeValue()
463
464 class Element(Node):
465 """
466 Element interface
467 """
468
469 # Element Attributes
470 # ------------------
471
472 def getTagName(self):
473 """The name of the element"""
474 return self.__class__.__name__
475
476 def getNodeName(self):
477 """The name of this node, depending on its type"""
478 return self.__class__.__name__
479
480 def getNodeType(self):
481 """A code representing the type of the node."""
482 return ELEMENT_NODE
483
484 def getNodeValue(self, type=type, st=type('')):
485 r=[]
486 for c in self.getChildren():
487 if type(c) is not st:
488 c=c.getNodeValue()
489 r.append(c)
490 return string.join(r,'')
491
492 def getParentNode(self):
493 """
494 The parent of this node. All nodes except Document
495 DocumentFragment and Attr may have a parent
496 """
497
498 # Element Methods
499 # ---------------
500
501 _attributes=()
502
503 def getAttribute(self, name): return getattr(self, name, None)
504 def getAttributeNode(self, name):
505 if hasattr(self, name):
506 return Attr(name, getattr(self, name))
507
508 def getAttributes(self):
509 d={}
510 for a in self._attributes:
511 d[a]=getattr(self, a, '')
512 return NamedNodeMap(d)
513
514 def getAttribute(self, name):
515 """Retrieves an attribute value by name."""
516 return None
517
518 def getAttributeNode(self, name):
519 """ Retrieves an Attr node by name or None if
520 there is no such attribute. """
521 return None
522
523 def getElementsByTagName(self, tagname):
524 """
525 Returns a NodeList of all the Elements with a given tag
526 name in the order in which they would be encountered in a
527 preorder traversal of the Document tree. Parameter: tagname
528 The name of the tag to match (* = all tags). Return Value: A new
529 NodeList object containing all the matched Elements.
530 """
531 nodeList = []
532 for child in self.getChildren():
533 if (child.getNodeType()==ELEMENT_NODE and \
534 child.getTagName()==tagname or tagname== '*'):
535
536 nodeList.append(child)
537
538 if hasattr(child, 'getElementsByTagName'):
539 n1 = child.getElementsByTagName(tagname)
540 nodeList = nodeList + n1._data
541 return NodeList(nodeList)
542
543 """
544 create aliases for all above functions in the pythony way.
545 """
546
547 def _get_TagName(self):
548 return self.getTagName()
549
550 def _get_NodeName(self):
551 return self.getNodeName()
552
553 def _get_NodeType(self):
554 return self.getNodeType()
555
556 def _get_NodeValue(self, type=type, st=type('')):
557 return self.getNodeValue(type,st)
558
559 def _get_ParentNode(self):
560 return self.getParentNode()
561
562 def _get_Attribute(self, name):
563 return self.getAttribute(name)
564
565 def _get_AttributeNode(self, name):
566 return self.getAttributeNode(name)
567
568 def _get_Attributes(self):
569 return self.getAttributes()
570
571 def _get_Attribute(self, name):
572 return self.getAttribute(name)
573
574 def _get_AttributeNode(self, name):
575 return self.getAttributeNode(name)
576
577 def _get_ElementsByTagName(self, tagname):
578 return self.getElementsByTagName(tagname)
579
580
581 class NodeList:
582 """
583 NodeList interface - Provides the abstraction of an ordered
584 collection of nodes.
585
586 Python extensions: can use sequence-style 'len', 'getitem', and
587 'for..in' constructs.
588 """
589
590 def __init__(self,list=None):
591 self._data = list or []
592
593 def __getitem__(self, index, type=type, st=type('')):
594 return self._data[index]
595
596 def __getslice__(self, i, j):
597 return self._data[i:j]
598
599 def item(self, index):
600 """
601 Returns the index-th item in the collection
602 """
603 try: return self._data[index]
604 except IndexError: return None
605
606 def getLength(self):
607 """
608 The length of the NodeList
609 """
610 return len(self._data)
611
612 __len__=getLength
613
614 """
615 create aliases for all above functions in the pythony way.
616 """
617
618 def _get_Length(self):
619 return self.getLength()
620
621 class NamedNodeMap:
622 """
623 NamedNodeMap interface - Is used to represent collections
624 of nodes that can be accessed by name. NamedNodeMaps are not
625 maintained in any particular order.
626
627 Python extensions: can use sequence-style 'len', 'getitem', and
628 'for..in' constructs, and mapping-style 'getitem'.
629 """
630
631 def __init__(self, data=None):
632 if data is None:
633 data = {}
634 self._data = data
635
636 def item(self, index):
637 """
638 Returns the index-th item in the map
639 """
640 try: return self._data.values()[index]
641 except IndexError: return None
642
643 def __getitem__(self, key):
644 if type(key)==type(1):
645 return self._data.values()[key]
646 else:
647 return self._data[key]
648
649 def getLength(self):
650 """
651 The length of the NodeList
652 """
653 return len(self._data)
654
655 __len__ = getLength
656
657 def getNamedItem(self, name):
658 """
659 Retrieves a node specified by name. Parameters:
660 name Name of a node to retrieve. Return Value A Node (of any
661 type) with the specified name, or None if the specified name
662 did not identify any node in the map.
663 """
664 if self._data.has_key(name):
665 return self._data[name]
666 return None
667
668 """
669 create aliases for all above functions in the pythony way.
670 """
671 def _get_Length(self):
672 return self.getLength()
673
674 def _get_NamedItem(self, name):
675 return self.getNamedItem(name)
676
677 class Attr(Node):
678 """
679 Attr interface - The Attr interface represents an attriubte in an
680 Element object. Attr objects inherit the Node Interface
681 """
682
683 def __init__(self, name, value, specified=1):
684 self.name = name
685 self.value = value
686 self.specified = specified
687
688 def getNodeName(self):
689 """
690 The name of this node, depending on its type
691 """
692 return self.name
693
694 def getName(self):
695 """
696 Returns the name of this attribute.
697 """
698 return self.name
699
700 def getNodeValue(self):
701 """
702 The value of this node, depending on its type
703 """
704 return self.value
705
706 def getNodeType(self):
707 """
708 A code representing the type of the node.
709 """
710 return ATTRIBUTE_NODE
711
712 def getSpecified(self):
713 """
714 If this attribute was explicitly given a value in the
715 original document, this is true; otherwise, it is false.
716 """
717 return self.specified
718
719 """
720 create aliases for all above functions in the pythony way.
721 """
722
723 def _get_NodeName(self):
724 return self.getNodeName()
725
726 def _get_Name(self):
727 return self.getName()
728
729 def _get_NodeValue(self):
730 return self.getNodeValue()
731
732 def _get_NodeType(self):
733 return self.getNodeType()
734
735 def _get_Specified(self):
736 return self.getSpecified()