📄 range.py
字号:
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -