summaryrefslogtreecommitdiffstats
path: root/lib/jython/Lib/xml/dom/Range.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/jython/Lib/xml/dom/Range.py')
-rw-r--r--lib/jython/Lib/xml/dom/Range.py1099
1 files changed, 1099 insertions, 0 deletions
diff --git a/lib/jython/Lib/xml/dom/Range.py b/lib/jython/Lib/xml/dom/Range.py
new file mode 100644
index 000000000..0b7a2802e
--- /dev/null
+++ b/lib/jython/Lib/xml/dom/Range.py
@@ -0,0 +1,1099 @@
+########################################################################
+#
+# File Name: Range.py
+#
+# Documentation: http://docs.4suite.com/4DOM/Range.py.html
+#
+"""
+WWW: http://4suite.com/4DOM e-mail: support@4suite.com
+
+Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved.
+See http://4suite.com/COPYRIGHT for license and copyright information
+"""
+
+
+from xml.dom import InvalidStateErr
+from xml.dom import InvalidNodeTypeErr
+from xml.dom import BadBoundaryPointsErr
+from xml.dom import IndexSizeErr
+from xml.dom import WrongDocumentErr
+
+from xml.dom import Node
+
+
+class Range:
+ readOnly =['startContainer',
+ 'startOffset',
+ 'endContainer',
+ 'endOffset',
+ 'collapsed',
+ 'commonAncestorContainer',
+ ]
+
+ POSITION_EQUAL = 1
+ POSITION_LESS_THAN = 2
+ POSITION_GREATER_THAN = 3
+
+ START_TO_START = 0
+ START_TO_END = 1
+ END_TO_END = 2
+ END_TO_START = 3
+
+ def __init__(self,ownerDocument):
+ self._ownerDocument = ownerDocument
+
+ self.__dict__['startContainer'] = ownerDocument
+ self.__dict__['startOffset'] = 0
+ self.__dict__['endContainer'] = ownerDocument
+ self.__dict__['endOffset'] = 0
+ self.__dict__['collapsed'] = 1
+ self.__dict__['commonAncestorContainer'] = ownerDocument
+
+ self.__dict__['detached'] = 0
+
+
+
+ def __setattr__(self,name,value):
+ if name in self.readOnly:
+ raise AttributeError, name
+ self.__dict__[name] = value
+
+ def __getattr__(self,name):
+ if name in self.readOnly:
+ #Means we are detached
+ raise InvalidStateErr()
+ raise AttributeError, name
+
+
+
+
+
+ def cloneContents(self):
+ """Clone the contents defined by this range"""
+
+ if self.detached:
+ raise InvalidStateErr()
+
+ df = self._ownerDocument.createDocumentFragment()
+
+ if self.startContainer == self.endContainer:
+ if self.startOffset == self.endOffset:
+ return df
+ if self.startContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ data = self.startContainer.substringData(self.startOffset,1+self.endOffset-self.startOffset)
+ tx = self._ownerDocument.createTextNode(data)
+ df.appendChild(tx)
+
+ else:
+ #Clone a set number of children
+ numDel = self.endOffset - self.startOffset+1
+ for ctr in range(numDel):
+ c = self.startContainer.childNodes[self.startOffset+ctr].cloneNode(1)
+ df.appendChild(c)
+
+ elif self.startContainer == self.commonAncestorContainer:
+ #Clone up the endContainer
+ #From the start to the end
+ lastKids = []
+ copyData = None
+ if self.endContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ copyData = self.endContainer.substringData(0,self.endOffset)
+ else:
+ numDel = self.endOffset
+ for ctr in range(numDel):
+ lastKids.append(self.endContainer.childNodes[ctr].cloneNode(1))
+
+ cur = self.endContainer
+ while cur.parentNode != self.commonAncestorContainer:
+
+ #Clone all of the way up
+ newCur = cur.cloneNode(0)
+ if copyData:
+ newCur.data = copyData
+ copyData = None
+ for k in lastKids:
+ newCur.appendChild(k)
+
+ lastKids = []
+ index = cur.parentNode.childNodes.index(cur)
+ for ctr in range(index):
+ lastKids.append(cur.parentNode.childNodes[ctr].cloneNode(1))
+ lastKids.append(newCur)
+ cur = cur.parentNode
+
+ newEnd = cur.cloneNode(0)
+ for k in lastKids:
+ newEnd.appendChild(k)
+
+ endAncestorChild = cur
+
+ #Extract up to the ancestor of end
+ for c in self.startContainer.childNodes:
+ if c == endAncestorChild:
+ break
+ df.appendChild(c.cloneNode(1))
+ df.appendChild(newEnd)
+
+ elif self.endContainer == self.commonAncestorContainer:
+ lastKids = []
+ copyData = None
+ if self.startContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+
+ copyData = self.startContainer.substringData(self.startOffset,1+len(self.startContainer.data)-self.startOffset)
+ else:
+ numDel = len(self.startContainer.childNodes) - self.startOffset
+ for ctr in range(numDel):
+ c = self.startContainer.childNodes[self.startOffset+ctr].cloneNode(1)
+ lastKids.append(c)
+
+ cur = self.startContainer
+ while cur.parentNode != self.commonAncestorContainer:
+ #Clone all of the way up
+ newCur = cur.cloneNode(0)
+ if copyData:
+ newCur.data = copyData
+ copyData = None
+ for k in lastKids:
+ newCur.appendChild(k)
+ lastKids = [newCur]
+
+ index = cur.parentNode.childNodes.index(cur)
+ for ctr in range(index+1,len(cur.parentNode.childNodes)):
+ lastKids.append(cur.parentNode.childNodes[ctr].cloneNode(1))
+ cur = cur.parentNode
+
+ startAncestorChild = cur
+ newStart = cur.cloneNode(0)
+ for k in lastKids:
+ newStart.appendChild(k)
+
+ df.appendChild(newStart)
+
+
+ #Extract up to the ancestor of start
+ startAncestorChild = cur
+ startIndex = self.endContainer.childNodes.index(cur)
+ lastAdded = None
+ for ctr in range(startIndex+1,self.endOffset+1):
+ c = self.endContainer.childNodes[ctr].cloneNode(1)
+ df.insertBefore(c,lastAdded)
+ lastAdded = c
+
+ else:
+ #From the start to the end
+ lastStartKids = []
+ startCopyData = None
+ if self.startContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+
+ startCopyData = self.startContainer.substringData(self.startOffset,1+len(self.startContainer.data)-self.startOffset)
+ else:
+ numDel = len(self.startContainer.childNodes) - self.startOffset
+ for ctr in range(numDel):
+ c = self.startContainer.childNodes[self.startOffset+ctr].cloneNode(1)
+ lastStartKids.append(c)
+
+ cur = self.startContainer
+ while cur.parentNode != self.commonAncestorContainer:
+ #Clone all of the way up
+ newCur = cur.cloneNode(0)
+ if startCopyData:
+ newCur.data = startCopyData
+ startCopyData = None
+ for k in lastStartKids:
+ newCur.appendChild(k)
+ lastStartKids = [newCur]
+
+
+ index = cur.parentNode.childNodes.index(cur)
+ for ctr in range(index+1,len(cur.parentNode.childNodes)):
+ lastStartKids.append(cur.parentNode.childNodes[ctr].cloneNode(1))
+ cur = cur.parentNode
+
+ startAncestorChild = cur
+
+ newStart = cur.cloneNode(0)
+ for k in lastStartKids:
+ newStart.appendChild(k)
+
+ df.appendChild(newStart)
+
+
+ lastEndKids = []
+ endCopyData = None
+ #Delete up the endContainer
+ #From the start to the end
+ if self.endContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ endCopyData = self.endContainer.substringData(0,self.endOffset)
+ else:
+ numDel = self.endOffset
+ for ctr in range(numDel):
+ c = self.endContainer.childNodes[ctr].cloneNode(1)
+ lastEndKids.append(c)
+
+ cur = self.endContainer
+ while cur.parentNode != self.commonAncestorContainer:
+ newCur = cur.cloneNode(0)
+ if endCopyData:
+ newCur.data = endCopyData
+ endCopyData = None
+ for k in lastEndKids:
+ newCur.appendChild(k)
+
+ lastEndKids = []
+ index = cur.parentNode.childNodes.index(cur)
+ for ctr in range(index):
+ lastEndKids.append(cur.parentNode.childNodes[ctr].cloneNode(1))
+ lastEndKids.append(newCur)
+ cur = cur.parentNode
+
+ endAncestorChild = cur
+
+ newEnd = cur.cloneNode(0)
+ for k in lastEndKids:
+ newEnd.appendChild(k)
+
+
+ cur = startAncestorChild
+ #Extract everything between us
+ startIndex = startAncestorChild.parentNode.childNodes.index(startAncestorChild)
+ endIndex = endAncestorChild.parentNode.childNodes.index(endAncestorChild)
+ for ctr in range(startIndex+1,endIndex):
+ c = startAncestorChild.parentNode.childNodes[ctr]
+ df.appendChild(c.cloneNode(1))
+ df.appendChild(newEnd)
+
+
+ #Adjust the containers
+ #FIXME What the heck is the spec talking about??
+ self.__dict__['endContainer'] = self.startContainer
+ self.__dict__['endOffset'] = self.startContainer
+ self.__dict__['commonAncestorContainer'] = self.startContainer
+ self.__dict__['collapsed'] = 1
+
+
+
+ return df
+
+
+ def cloneRange(self):
+ if self.detached:
+ raise InvalidStateErr()
+
+ newRange = Range(self._ownerDocument)
+ newRange.setStart(self.startContainer,self.startOffset)
+ newRange.setEnd(self.endContainer,self.endOffset)
+ return newRange
+
+ def collapse(self,toStart):
+ """Collapse the range"""
+ if self.detached:
+ raise InvalidStateErr()
+
+ if toStart:
+ self.__dict__['endContainer'] = self.startContainer
+ self.__dict__['endOffset'] = self.startOffset
+ else:
+ self.__dict__['startContainer'] = self.endContainer
+ self.__dict__['startOffset'] = self.endOffset
+
+ self.__dict__['collapsed'] = 1
+ self.__dict__['commonAncestorContainer'] = self.startContainer
+
+
+ def compareBoundaryPoints(self,how,sourceRange):
+ if self.detached:
+ raise InvalidStateErr()
+
+ if not hasattr(sourceRange,'_ownerDocument') or sourceRange._ownerDocument != self._ownerDocument or not isinstance(sourceRange,Range):
+ raise WrongDocumentErr()
+
+ if how == self.START_TO_START:
+ ac = self.startContainer
+ ao = self.startOffset
+ bc = sourceRange.startContainer
+ bo = sourceRange.startOffset
+ elif how == self.START_TO_END:
+ ac = self.startContainer
+ ao = self.startOffset
+ bc = sourceRange.endContainer
+ bo = sourceRange.endOffset
+ elif how == self.END_TO_END:
+ ac = self.endContainer
+ ao = self.endOffset
+ bc = sourceRange.endContainer
+ bo = sourceRange.endOffset
+ elif how == self.END_TO_START:
+ ac = self.endContainer
+ ao = self.endOffset
+ bc = sourceRange.startContainer
+ bo = sourceRange.startOffset
+ else:
+ raise TypeError, how
+
+ pos = self.__comparePositions(ac,ao,bc,bo)
+ if pos == self.POSITION_EQUAL:
+ return 0
+ elif pos == self.POSITION_LESS_THAN:
+ return -1
+ return 1
+
+ def deleteContents(self):
+ """Delete the contents defined by this range"""
+
+
+ #NOTE Use 4DOM ReleaseNode cause it is interface safe
+ from xml.dom.ext import ReleaseNode
+
+ if self.detached:
+ raise InvalidStateErr()
+
+ if self.startContainer == self.endContainer:
+ if self.startOffset == self.endOffset:
+ return
+ if self.startContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ self.startContainer.deleteData(self.startOffset,1+self.endOffset-self.startOffset)
+
+ else:
+ #Delete a set number of children
+ numDel = self.endOffset - self.startOffset+1
+ for ctr in range(numDel):
+ c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset])
+ ReleaseNode(c)
+
+ self.__dict__['endContainer'] = self.startContainer
+ self.__dict__['endOffset'] = self.endContainer
+ self.__dict__['commonAncestorContainer'] = self.endContainer
+ self.__dict__['collapsed'] = 1
+
+ elif self.startContainer == self.commonAncestorContainer:
+ #Delete up the endContainer
+ #From the start to the end
+ if self.endContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ self.endContainer.deleteData(0,self.endOffset)
+ else:
+ numDel = self.endOffset
+ for ctr in range(numDel):
+ c = self.endContainer.removeChild(self.endContainer.childNodes[0])
+ ReleaseNode(c)
+
+ cur = self.endContainer
+ while cur.parentNode != self.commonAncestorContainer:
+ while cur.previousSibling:
+ c = cur.parentNode.removeChild(cur.previousSibling)
+ ReleaseNode(c)
+ cur = cur.parentNode
+
+ #Delete up to the ancestor of end
+ endAncestorChild = cur
+ while self.startContainer.firstChild != endAncestorChild:
+ c = self.startContainer.removeChild(self.startContainer.firstChild)
+ ReleaseNode(c)
+ elif self.endContainer == self.commonAncestorContainer:
+ if self.startContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ self.startContainer.deleteData(self.startOffset,1+len(self.startContainer.data)-self.startOffset)
+ else:
+ numDel = len(self.startContainer.childNodes) - self.startOffset
+ for ctr in range(numDel):
+ c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset])
+ ReleaseNode(c)
+
+ cur = self.startContainer
+ while cur.parentNode != self.commonAncestorContainer:
+ while cur.nextSibling:
+ c = cur.parentNode.removeChild(cur.nextSibling)
+ ReleaseNode(c)
+ cur = cur.parentNode
+
+ startAncestorChild = cur
+
+ #Delete up to the ancestor of start
+ startAncestorChild = cur
+ startIndex = self.endContainer.childNodes.index(cur)
+ numDel = self.endOffset - startIndex
+ for ctr in range(numDel):
+ c = self.endContainer.removeChild(startAncestorChild.nextSibling)
+ ReleaseNode(c)
+
+ else:
+ #From the start to the end
+ if self.startContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ self.startContainer.deleteData(self.startOffset,1+len(self.startContainer.data)-self.startOffset)
+ else:
+ numDel = len(self.startContainer.childNodes) - self.startOffset
+ for ctr in range(numDel):
+ c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset])
+ ReleaseNode(c)
+
+ cur = self.startContainer
+ while cur.parentNode != self.commonAncestorContainer:
+ while cur.nextSibling:
+ c = cur.parentNode.removeChild(cur.nextSibling)
+ ReleaseNode(c)
+ cur = cur.parentNode
+
+ startAncestorChild = cur
+ #Delete up the endContainer
+ #From the start to the end
+ if self.endContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ self.endContainer.deleteData(0,self.endOffset)
+ else:
+ numDel = self.endOffset
+ for ctr in range(numDel):
+ c = self.endContainer.removeChild(self.endContainer.childNodes[0])
+ ReleaseNode(c)
+
+ cur = self.endContainer
+ while cur.parentNode != self.commonAncestorContainer:
+ while cur.previousSibling:
+ c = cur.parentNode.removeChild(cur.previousSibling)
+ ReleaseNode(c)
+ cur = cur.parentNode
+
+ endAncestorChild = cur
+
+ cur = startAncestorChild
+ #Delete everything between us
+ while cur.nextSibling != endAncestorChild:
+ c = cur.parentNode.removeChild(cur.nextSibling)
+ ReleaseNode(c)
+
+ #Adjust the containers
+ #FIXME What the heck is the spec talking about??
+ self.__dict__['endContainer'] = self.startContainer
+ self.__dict__['endOffset'] = self.startContainer
+ self.__dict__['commonAncestorContainer'] = self.startContainer
+ self.__dict__['collapsed'] = 1
+
+ return None
+
+ def detach(self):
+ self.detached = 1
+ del self.startContainer
+ del self.endContainer
+ del self.startOffset
+ del self.endOffset
+ del self.collapsed
+ del self.commonAncestorContainer
+
+ def extractContents(self):
+ """Extract the contents defined by this range"""
+
+
+ if self.detached:
+ raise InvalidStateErr()
+
+ df = self._ownerDocument.createDocumentFragment()
+
+ if self.startContainer == self.endContainer:
+ if self.startOffset == self.endOffset:
+ return df
+ if self.startContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ data = self.startContainer.substringData(self.startOffset,1+self.endOffset-self.startOffset)
+ self.startContainer.deleteData(self.startOffset,1+self.endOffset-self.startOffset)
+
+ tx = self._ownerDocument.createTextNode(data)
+ df.appendChild(tx)
+
+ else:
+ #Extrace a set number of children
+
+ numDel = self.endOffset - self.startOffset+1
+ for ctr in range(numDel):
+ c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset])
+ df.appendChild(c)
+
+ elif self.startContainer == self.commonAncestorContainer:
+ #Delete up the endContainer
+ #From the start to the end
+ lastKids = []
+ copyData = None
+ #Delete up the endContainer
+ #From the start to the end
+ if self.endContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ copyData = self.endContainer.substringData(0,self.endOffset)
+ self.endContainer.deleteData(0,self.endOffset)
+ else:
+ numDel = self.endOffset
+ for ctr in range(numDel):
+ c = self.endContainer.removeChild(self.endContainer.childNodes[0])
+ lastKids.append(c)
+
+ cur = self.endContainer
+ while cur.parentNode != self.commonAncestorContainer:
+
+ #Clone all of the way up
+ newCur = cur.cloneNode(0)
+ if copyData:
+ newCur.data = copyData
+ copyData = None
+ for k in lastKids:
+ newCur.appendChild(k)
+ lastKids = [newCur]
+
+ while cur.previousSibling:
+ c = cur.parentNode.removeChild(cur.previousSibling)
+ lastKids = [c] + lastKids
+ cur = cur.parentNode
+
+ newEnd = cur.cloneNode(0)
+ for k in lastKids:
+ newEnd.appendChild(k)
+
+ endAncestorChild = cur
+
+ #Extract up to the ancestor of end
+ while self.startContainer.firstChild != endAncestorChild:
+ c = self.startContainer.removeChild(self.startContainer.firstChild)
+ df.appendChild(c)
+ df.appendChild(newEnd)
+
+ elif self.endContainer == self.commonAncestorContainer:
+ lastKids = []
+ copyData = None
+ if self.startContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+
+ copyData = self.startContainer.substringData(self.startOffset,1+len(self.startContainer.data)-self.startOffset)
+ self.startContainer.deleteData(self.startOffset,1+len(self.startContainer.data)-self.startOffset)
+ else:
+ numDel = len(self.startContainer.childNodes) - self.startOffset
+ for ctr in range(numDel):
+ c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset])
+ lastKids.append(c)
+
+ cur = self.startContainer
+ while cur.parentNode != self.commonAncestorContainer:
+ #Clone all of the way up
+ newCur = cur.cloneNode(0)
+ if copyData:
+ newCur.data = copyData
+ copyData = None
+ for k in lastKids:
+ newCur.appendChild(k)
+ lastKids = [newCur]
+
+ while cur.nextSibling:
+ c = cur.parentNode.removeChild(cur.nextSibling)
+ lastKids.append(c)
+ cur = cur.parentNode
+
+ startAncestorChild = cur
+ newStart = cur.cloneNode(0)
+ for k in lastKids:
+ newStart.appendChild(k)
+
+ df.appendChild(newStart)
+
+
+ #Extract up to the ancestor of start
+ startAncestorChild = cur
+ startIndex = self.endContainer.childNodes.index(cur)
+ lastAdded = None
+ numDel = self.endOffset - startIndex
+ for ctr in range(numDel):
+ c = self.endContainer.removeChild(startAncestorChild.nextSibling)
+ df.insertBefore(c,lastAdded)
+ lastAdded = c
+
+ else:
+ #From the start to the end
+ lastStartKids = []
+ startCopyData = None
+ if self.startContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+
+ startCopyData = self.startContainer.substringData(self.startOffset,1+len(self.startContainer.data)-self.startOffset)
+ self.startContainer.deleteData(self.startOffset,1+len(self.startContainer.data)-self.startOffset)
+ else:
+ numDel = len(self.startContainer.childNodes) - self.startOffset
+ for ctr in range(numDel):
+ c = self.startContainer.removeChild(self.startContainer.childNodes[self.startOffset])
+ lastStartKids.append(c)
+
+ cur = self.startContainer
+ while cur.parentNode != self.commonAncestorContainer:
+ #Clone all of the way up
+ newCur = cur.cloneNode(0)
+ if startCopyData:
+ newCur.data = startCopyData
+ startCopyData = None
+ for k in lastStartKids:
+ newCur.appendChild(k)
+ lastStartKids = [newCur]
+
+ while cur.nextSibling:
+ c = cur.parentNode.removeChild(cur.nextSibling)
+ lastStartKids.append(c)
+ cur = cur.parentNode
+
+ startAncestorChild = cur
+
+ newStart = cur.cloneNode(0)
+ for k in lastStartKids:
+ newStart.appendChild(k)
+
+ df.appendChild(newStart)
+
+
+ lastEndKids = []
+ endCopyData = None
+ #Delete up the endContainer
+ #From the start to the end
+ if self.endContainer.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Adjust the character data
+ endCopyData = self.endContainer.substringData(0,self.endOffset)
+ self.endContainer.deleteData(0,self.endOffset)
+ else:
+ numDel = self.endOffset
+ for ctr in range(numDel):
+ c = self.endContainer.removeChild(self.endContainer.childNodes[0])
+ lastEndKids.append(c)
+
+ cur = self.endContainer
+ while cur.parentNode != self.commonAncestorContainer:
+ newCur = cur.cloneNode(0)
+ if endCopyData:
+ newCur.data = endCopyData
+ endCopyData = None
+ for k in lastEndKids:
+ newCur.appendChild(k)
+ lastEndKids = [newCur]
+ while cur.previousSibling:
+ c = cur.parentNode.removeChild(cur.previousSibling)
+ lastEndKids = [c] + lastEndKids
+ cur = cur.parentNode
+
+ endAncestorChild = cur
+
+ newEnd = cur.cloneNode(0)
+ for k in lastEndKids:
+ newEnd.appendChild(k)
+
+
+ cur = startAncestorChild
+ #Extract everything between us
+ while cur.nextSibling != endAncestorChild:
+ c = cur.parentNode.removeChild(cur.nextSibling)
+ df.appendChild(c)
+ df.appendChild(newEnd)
+
+
+ #Adjust the containers
+ #FIXME What the heck is the spec talking about??
+ self.__dict__['endContainer'] = self.startContainer
+ self.__dict__['endOffset'] = self.startContainer
+ self.__dict__['commonAncestorContainer'] = self.startContainer
+ self.__dict__['collapsed'] = 1
+
+
+
+ return df
+
+
+ def insertNode(self,newNode):
+ """Insert a node at the starting point"""
+
+ if self.detached:
+ raise InvalidStateErr()
+
+ if newNode.nodeType in [Node.ATTRIBUTE_NODE,
+ Node.ENTITY_NODE,
+ Node.NOTATION_NODE,
+ Node.DOCUMENT_NODE,
+ ]:
+ raise InvalidNodeTypeErr()
+
+ if self.startContainer.nodeType == Node.TEXT_NODE:
+ #Split the text at the boundary. Insert the node after this
+ otherText = self.startContainer.substringData(self.startOffset,len(self.startContainer.data))
+ self.startContainer.deleteData(self.startOffset,len(self.startContainer.data))
+ newText = self._ownerDocument.createTextNode(otherText)
+ self.startContainer.parentNode.insertBefore(newText,self.startContainer.nextSibling)
+
+ newText.parentNode.insertBefore(newNode,newText)
+ elif self.startContainer.nodeType in [Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ raise HierarchyRequestErr()
+ else:
+ curNode = self.startContainer.childNodes[self.startOffset]
+ self.startContainer.insertBefore(newNode,curNode.nextSibling)
+
+
+
+ def selectNode(self,refNode):
+ """Select a node"""
+ if self.detached:
+ raise InvalidStateErr()
+
+ self.__validateRefNode(refNode)
+
+ self.__dict__['startContainer'] = refNode.parentNode
+ self.__dict__['endContainer'] = refNode.parentNode
+
+
+ index = refNode.parentNode.childNodes.index(refNode)
+ self.__dict__['startOffset'] = index
+ self.__dict__['endOffset'] = index+1
+
+ self.__dict__['collapsed'] = 0
+ self.__dict__['commonAncestorContainer'] = refNode.parentNode
+
+
+ def selectNodeContents(self,refNode):
+ """Select a node"""
+ if self.detached:
+ raise InvalidStateErr()
+
+ self.__validateBoundary(refNode,0)
+
+
+ self.__dict__['startContainer'] = refNode
+ self.__dict__['endContainer'] = refNode
+
+
+ self.__dict__['startOffset'] = 0
+ self.__dict__['endOffset'] = len(refNode.childNodes)
+
+ self.__dict__['collapsed'] = self.startOffset == self.endOffset
+ self.__dict__['commonAncestorContainer'] = refNode
+
+
+
+ def setEnd(self,parent,offset):
+ """Set the ranges end container and offset"""
+
+ #Check for errors
+ if self.detached:
+ raise InvalidStateErr()
+
+ self.__validateBoundary(parent,offset)
+
+ self.__dict__['endContainer'] = parent
+ self.__dict__['endOffset'] = offset
+
+ self.__dict__['collapsed'] = 0
+
+ pos = self.__comparePositions(parent,offset,self.startContainer,self.startOffset)
+ self.__dict__['collapsed'] = (pos == self.POSITION_EQUAL)
+ if pos == self.POSITION_LESS_THAN:
+ self.__dict__['startContainer'] = parent
+ self.__dict__['startOffset'] = offset
+ self.__dict__['collapsed'] = 1
+
+ self.__calculateCommonAncestor()
+
+ def setEndAfter(self,node):
+
+ self.__validateRefNode(node)
+
+ cont = node.parentNode
+ index = cont.childNodes.index(node)
+ self.setEnd(cont,index+1)
+
+ def setEndBefore(self,node):
+
+ self.__validateRefNode(node)
+
+ cont = node.parentNode
+ index = cont.childNodes.index(node)
+ self.setEnd(cont,index)
+
+
+
+ def setStart(self,parent,offset):
+ """Set the ranges start container and offset"""
+
+ #Check for errors
+ if self.detached:
+ raise InvalidStateErr()
+
+ self.__validateBoundary(parent,offset)
+
+ self.__dict__['startContainer'] = parent
+ self.__dict__['startOffset'] = offset
+
+
+ pos = self.__comparePositions(parent,offset,self.endContainer,self.endOffset)
+ self.__dict__['collapsed'] = (pos == self.POSITION_EQUAL)
+
+ if pos == self.POSITION_GREATER_THAN:
+ self.__dict__['endContainer'] = parent
+ self.__dict__['endOffset'] = offset
+ self.__dict__['collapsed'] = 1
+
+ self.__calculateCommonAncestor()
+
+ def setStartAfter(self,node):
+
+ self.__validateRefNode(node)
+
+ cont = node.parentNode
+ index = cont.childNodes.index(node)
+ self.setStart(cont,index+1)
+
+ def setStartBefore(self,node):
+
+ self.__validateRefNode(node)
+
+ cont = node.parentNode
+ index = cont.childNodes.index(node)
+ self.setStart(cont,index)
+
+ def surrondContents(self,newParent):
+ """Surrond the range with this node"""
+ if self.detached:
+ raise InvalidStateErr()
+
+ if newParent.nodeType in [Node.ATTRIBUTE_NODE,
+ Node.ENTITY_NODE,
+ Node.DOCUMENT_TYPE_NODE,
+ Node.NOTATION_NODE,
+ Node.DOCUMENT_NODE,
+ Node.DOCUMENT_FRAGMENT_NODE]:
+ raise InvalidNodeTypeErr()
+
+ #See is we have element nodes that are partially selected
+ if self.startContainer.nodeType not in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ if self.commonAncestorContainer not in [self.startContainer,self.startContainer.parentNode]:
+ #This is partially selected because our parent is not the common ancestor
+ raise BadBoundaryPointsErr()
+ if self.endContainer.nodeType not in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ if self.commonAncestorContainer not in [self.endContainer,self.endContainer.parentNode]:
+ #This is partially selected because our parent is not the common ancestor
+ raise BadBoundaryPointsErr()
+
+ #All good, do the insert
+ #Remove children from newPArent
+ for c in newParent.childNodes:
+ newParent.removeChild(c)
+
+ df = self.extractContents()
+
+ self.insertNode(newParent)
+
+ newParent.appendChild(df)
+
+ self.selectNode(newParent)
+
+
+ def toString(self):
+ if self.detached:
+ raise InvalidStateErr()
+
+ df = self.cloneContents()
+
+
+ res = self.__recurseToString(df)
+
+
+ from xml.dom.ext import ReleaseNode
+ ReleaseNode(df)
+
+ return res
+
+ #Internal Functions#
+
+
+ def __validateBoundary(self,node,offset):
+ """Make sure the node is a legal boundary"""
+
+ if not hasattr(node,'nodeType'):
+ raise InvalidNodeTypeErr()
+
+
+ #Check for proper node type
+ curNode = node
+ while curNode:
+ if curNode.nodeType in [Node.ENTITY_NODE,
+ Node.NOTATION_NODE,
+ Node.DOCUMENT_TYPE_NODE,
+ ]:
+ raise InvalidNodeTypeErr()
+ curNode = curNode.parentNode
+
+ #Check number of cild units
+ if offset < 0:
+ raise IndexSizeErr()
+
+ if node.nodeType in [Node.TEXT_NODE,
+ Node.COMMENT_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE]:
+ #Child units are characters
+ if offset > len(node.data):
+ raise IndexSizeErr()
+ else:
+ if offset > len(node.childNodes):
+ raise IndexSizeErr()
+
+ def __validateRefNode(self,node):
+
+ if not hasattr(node,'nodeType'):
+ raise InvalidNodeTypeErr()
+
+ cur = node
+ while cur.parentNode:
+ cur = cur.parentNode
+ if cur.nodeType not in [Node.ATTRIBUTE_NODE,
+ Node.DOCUMENT_NODE,
+ Node.DOCUMENT_FRAGMENT_NODE,
+ ]:
+ raise InvalidNodeTypeErr()
+
+ if node.nodeType in [Node.DOCUMENT_NODE,
+ Node.DOCUMENT_FRAGMENT_NODE,
+ Node.ATTRIBUTE_NODE,
+ Node.ENTITY_NODE,
+ Node.NOTATION_NODE,
+ ]:
+
+ raise InvalidNodeTypeErr()
+
+
+ def __comparePositions(self,aContainer,aOffset,bContainer,bOffset):
+ """Compare Boundary Positions Section 2.5"""
+
+ if aContainer == bContainer:
+ #CASE 1
+ if aOffset == bOffset:
+ return self.POSITION_EQUAL
+ elif aOffset < bOffset:
+ return self.POSITION_LESS_THAN
+ else:
+ return self.POSITION_GREATER_THAN
+ #CASE 2
+ bAncestors = []
+ cur = bContainer
+ while cur:
+ bAncestors.append(cur)
+ cur = cur.parentNode
+
+ for ctr in range(len(aContainer.childNodes)):
+ c = aContainer.childNodes[ctr]
+ if c in bAncestors:
+ if aOffset <= ctr:
+ return self.POSITION_LESS_THAN
+ else:
+ return self.POSITION_GREATER_THAN
+
+ #CASE 3
+ aAncestors = []
+ cur = aContainer
+ while cur:
+ aAncestors.append(cur)
+ cur = cur.parentNode
+
+ for ctr in range(len(bContainer.childNodes)):
+ c = bContainer.childNodes[ctr]
+ if c in aAncestors:
+ if ctr < bOffset:
+ return self.POSITION_LESS_THAN
+ else:
+ return self.POSITION_GREATER_THAN
+
+
+
+ #CASE 4
+ #Check the "Following axis" of A.
+ #If B is in the axis, then A is before B
+
+ curr = aContainer
+ while curr != aContainer.ownerDocument:
+ sibling = curr.nextSibling
+ while sibling:
+ if curr == bContainer:
+ return self.POSITION_LESS_THAN
+ rt = self.__checkDescendants(sibling,bContainer)
+ if rt:
+ return self.POSITION_LESS_THAN
+ sibling = sibling.nextSibling
+ curr = ((curr.nodeType == Node.ATTRIBUTE_NODE) and
+ curr.ownerElement or curr.parentNode)
+
+ #Not in the following, return POSITION_LESS_THAN
+ return self.POSITION_GREATER_THAN
+
+ def __checkDescendants(self,sib,b):
+ for c in sib.childNodes:
+ if c == b: return 1
+ if self.__checkDescendants(c,b): return 1
+ return 0
+
+
+ def __calculateCommonAncestor(self):
+
+ if self.startContainer == self.endContainer:
+ self.__dict__['commonAncestorContainer'] = self.startContainer
+
+ startAncestors = []
+ cur = self.startContainer
+ while cur:
+ startAncestors.append(cur)
+ cur = cur.parentNode
+
+ cur = self.endContainer
+ while cur:
+ if cur in startAncestors:
+ self.__dict__['commonAncestorContainer'] = cur
+ return
+ cur = cur.parentNode
+
+ #Hmm no ancestor
+ raise BadBoundaryPointsErr()
+
+
+ def __recurseToString(self,node):
+
+ if node.nodeType in [Node.TEXT_NODE,
+ Node.CDATA_SECTION_NODE]:
+ return node.data
+ else:
+ res = ""
+ for c in node.childNodes:
+ res = res + self.__recurseToString(c)
+ return res