void RangeImpl::checkReadOnly(DOM_Node& start, DOM_Node& end, unsigned int startOffset, unsigned int endOffset) { if ((start == null) || (end == null) ) return; //if both start and end are text check and return if (start.getNodeType() == DOM_Node::TEXT_NODE) { if (start.fImpl->isReadOnly()) { throw DOM_DOMException( DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null); } if (start == end) return; } //set the start and end nodes to check DOM_Node sNode = start.getFirstChild(); for(unsigned int i = 0; i<startOffset; i++) sNode = sNode.getNextSibling(); DOM_Node eNode; if (end.getNodeType() == DOM_Node::TEXT_NODE) { eNode = end; //need to check only till this node } else { //need to check all the kids that fall before the end offset value eNode = end.getFirstChild(); for (unsigned int i = 0; i<endOffset-1; i++) eNode = eNode.getNextSibling(); } //recursivly search if any node is readonly recurseTreeAndCheck(sNode, eNode); }
void RangeImpl::selectNode(const DOM_Node& refNode) { validateNode(refNode); if ( !isLegalContainedNode(refNode)) { throw DOM_RangeException( DOM_RangeException::INVALID_NODE_TYPE_ERR, null); } //First check for the text type node if (refNode.getNodeType() == DOM_Node::TEXT_NODE) { //The node itself is the container. fStartContainer = refNode; fEndContainer = refNode; //Select all the contents of the node fStartOffset = 0; fEndOffset = ((DOM_Text &)refNode).getLength(); return; } DOM_Node parent = refNode.getParentNode(); if (parent != null ) // REVIST: what to do if it IS null? { fStartContainer = parent; fEndContainer = parent; unsigned int i = 0; for (DOM_Node n = parent.getFirstChild(); n!=null, n!=refNode; n = n.getNextSibling()) { i++; } fStartOffset = i; fEndOffset = fStartOffset+1; } }
//====================================================================== //====================================================================== char* XMLDocument::getValue(DOM_Node currNode, char* path, DataTypeAttribute** dtAttributes) { if (mDoc == NULL) return NULL; if (path == NULL) return NULL; DOM_Node child = getNode(currNode, path, dtAttributes); if (child == NULL) return NULL; child = child.getFirstChild(); if (child == NULL) return NULL; // If siblings exist, this is not an leaf, but a branch DOM_Node sib = child.getNextSibling(); if (sib != NULL) return NULL; if (child.getNodeType() != DOM_Node::TEXT_NODE && child.getNodeType() != DOM_Node::CDATA_SECTION_NODE) return NULL; return child.getNodeValue().transcode(); }
DOM_Node XMLDocument::getNode(DOM_Node currNode, char* path, DataTypeAttribute** dtAttributes) { if (path == NULL) return NULL_DOM_Node; char* currName = currNode.getNodeName().transcode(); if (strcmp(currName, path) == 0 && (dtAttributes == NULL || doAttributesMatch(currNode, dtAttributes))) { delete[] currName; return currNode; } delete[] currName; char* cp = strchr(path, '.'); char pathName[256]; if (cp == NULL) strcpy(pathName, path); else { strncpy(pathName, path, cp - path); pathName[cp - path] = '\0'; } DOM_Node child = currNode.getFirstChild(); while (child != NULL) { char* childName = child.getNodeName().transcode(); if (child.getNodeType() != DOM_Node::ELEMENT_NODE) { child = child.getNextSibling(); delete[] childName; continue; } if (strcmp(pathName, childName) == 0) { if (cp != NULL) { delete[] childName; return getNode(child, cp+1, dtAttributes); } if (dtAttributes != NULL) { if (!doAttributesMatch(child, dtAttributes)) { child = child.getNextSibling(); delete[] childName; continue; } } delete[] childName; return child; } delete[] childName; child = child.getNextSibling(); } return NULL_DOM_Node; }
void RangeImpl::checkIndex(const DOM_Node& node, unsigned int offset) const { if (offset < 0) { throw DOM_DOMException( DOM_DOMException::INDEX_SIZE_ERR, null ); } short type = node.getNodeType(); if((type == DOM_Node::TEXT_NODE || type == DOM_Node::CDATA_SECTION_NODE || type == DOM_Node::COMMENT_NODE || type == DOM_Node::PROCESSING_INSTRUCTION_NODE)) { if (offset > node.getNodeValue().length()) throw DOM_DOMException( DOM_DOMException::INDEX_SIZE_ERR, null ); else return; } DOM_Node child = node.getFirstChild(); unsigned int i = 0; for (; child != null; i++) { child = child.getNextSibling(); } if (i < offset) { throw DOM_DOMException( DOM_DOMException::INDEX_SIZE_ERR, null ); } }
//====================================================================== //====================================================================== bool XMLDocument::setValue(DOM_Node currNode, char* path, DataTypeAttribute** dtAttributes, char* value) { if (mDoc == NULL) return false; if (path == NULL) return false; DOM_Node child = getNode(currNode, path, dtAttributes); if (child == NULL) return false; DOM_Node parent = child.getParentNode(); if (parent == NULL) return false; DOM_Node grandChild = child.getFirstChild(); short nType = DOM_Node::TEXT_NODE; if (grandChild != NULL) { nType = grandChild.getNodeType(); if (nType != DOM_Node::TEXT_NODE && nType != DOM_Node::CDATA_SECTION_NODE) return false; } char* childName = child.getNodeName().transcode(); DOM_NamedNodeMap nnodeMap = child.getAttributes(); parent.removeChild(child); DOM_Element childElement = mDoc.createElement(childName); delete[] childName; for (unsigned int i = 0; i < nnodeMap.getLength(); i++) { DOM_Node attNode = nnodeMap.item(i); childElement.setAttribute(attNode.getNodeName(), attNode.getNodeValue()); } if (nType == DOM_Node::TEXT_NODE) { DOM_Text childText = mDoc.createTextNode((value == NULL)?"":value); childElement.appendChild(childText); } else { DOM_CDATASection childCData = mDoc.createCDATASection((value == NULL)?"":value); childElement.appendChild(childCData); } parent.appendChild(childElement); return true; }
/** * Traverses the "right boundary" of this range and * operates on each "boundary node" according to the * how parameter. It is a-priori assumed * by this method that the right boundary does * not contain the range's start container. * * A "right boundary" is best visualized by thinking * of a sample tree: * A * /|\ * / | \ * / | \ * B C D * /|\ /|\ * E F G H I J * * Imagine first a range that begins between the * "E" and "F" nodes and ends between the * "I" and "J" nodes. The start container is * "B" and the end container is "D". Given this setup, * the following applies: * * Partially Selected Nodes: B, D<br> * Fully Selected Nodes: F, G, C, H, I * * The "right boundary" is the highest subtree node * that contains the ending container. The root of * this subtree is always partially selected. * * In this example, the nodes that are traversed * as "right boundary" nodes are: H, I, and D. * */ DOM_Node RangeImpl::traverseRightBoundary( DOM_Node root, int how ) { DOM_Node next = getSelectedNode( fEndContainer, fEndOffset-1 ); bool isFullySelected = ( next!=fEndContainer ); if ( next==root ) return traverseNode( next, isFullySelected, false, how ); DOM_Node parent = next.getParentNode(); DOM_Node clonedParent = traverseNode( parent, false, false, how ); while( parent!=null ) { while( next!=null ) { DOM_Node prevSibling = next.getPreviousSibling(); DOM_Node clonedChild = traverseNode( next, isFullySelected, false, how ); if ( how!=DELETE_CONTENTS ) { clonedParent.insertBefore( clonedChild, clonedParent.getFirstChild() ); } isFullySelected = true; next = prevSibling; } if ( parent==root ) return clonedParent; next = parent.getPreviousSibling(); parent = parent.getParentNode(); DOM_Node clonedGrandParent = traverseNode( parent, false, false, how ); if ( how!=DELETE_CONTENTS ) clonedGrandParent.appendChild( clonedParent ); clonedParent = clonedGrandParent; } // should never occur return null; }
/** * Utility method to retrieve a child node by index. This method * assumes the caller is trying to find out which node is * selected by the given index. Note that if the index is * greater than the number of children, this implies that the * first node selected is the parent node itself. * */ DOM_Node RangeImpl::getSelectedNode( DOM_Node container, int offset ) { if ( container.getNodeType() == DOM_Node::TEXT_NODE ) return container; // This case is an important convenience for // traverseRightBoundary() if ( offset<0 ) return container; DOM_Node child = container.getFirstChild(); while( child!=null && offset > 0 ) { --offset; child = child.getNextSibling(); } if ( child!=null ) return child; return container; }
DOM_Node TreeWalkerImpl::getFirstChild (DOM_Node node) { DOM_Node result; if (node.isNull()) return result; DOM_Node newNode = node.getFirstChild(); if (newNode.isNull()) return result; short accept = acceptNode(newNode); if (accept == DOM_NodeFilter::FILTER_ACCEPT) return newNode; else if (accept == DOM_NodeFilter::FILTER_SKIP && newNode.hasChildNodes()) { return getFirstChild(newNode); } return getNextSibling(newNode); }
DOM_Node RangeImpl::nextNode(const DOM_Node& node, bool visitChildren) const { if (node == null) return null; DOM_Node result; if (visitChildren) { result = node.getFirstChild(); if (result != null) { return result; } } // if hasSibling, return sibling result = node.getNextSibling(); if (result != null) { return result; } // return parent's 1st sibling. DOM_Node parent = node.getParentNode(); while ( (parent != null) && (parent != fDocument) ) { result = parent.getNextSibling(); if (result != null) { return result; } else { parent = parent.getParentNode(); if (parent == fEndContainer) return parent; } } // end of list, return null return null; }
DOM_Node XMLDocument::clone(DOM_Node currNode) { switch (currNode.getNodeType()) { case DOM_Node::ELEMENT_NODE: { DOM_Element elem = mDoc.createElement(currNode.getNodeName()); DOM_NamedNodeMap nnodeMap = currNode.getAttributes(); for (unsigned int i = 0; i < nnodeMap.getLength(); i++) { DOM_Node attNode = nnodeMap.item(i); elem.setAttribute(attNode.getNodeName(), attNode.getNodeValue()); } DOM_Node child = currNode.getFirstChild(); while (child != NULL) { DOM_Node cNode = clone(child); if (cNode != NULL) elem.appendChild(cNode); child = child.getNextSibling(); } return (DOM_Node)elem; } case DOM_Node::TEXT_NODE: { DOM_Text childText = mDoc.createTextNode(currNode.getNodeValue()); return (DOM_Node)childText; } case DOM_Node::CDATA_SECTION_NODE: { DOM_CDATASection childCData = mDoc.createCDATASection(currNode.getNodeValue()); return (DOM_Node)childCData; } default: { return NULL_DOM_Node; } } }
DOM_Node NodeIteratorImpl::nextNode (DOM_Node node, bool visitChildren) { if (fDetached) throw DOM_DOMException(DOM_DOMException::INVALID_STATE_ERR, null); if (node.isNull()) return fRoot; DOM_Node result; // only check children if we visit children. if (visitChildren) { //if hasChildren, return 1st child. if (node.hasChildNodes()) { result = node.getFirstChild(); return result; } } // if hasSibling, return sibling if (node != fRoot) { result = node.getNextSibling(); if (! result.isNull()) return result; // return parent's 1st sibling. DOM_Node parent = node.getParentNode(); while (!parent.isNull() && parent != fRoot) { result = parent.getNextSibling(); if (!result.isNull()) { return result; } else { parent = parent.getParentNode(); } } // while (parent != null && parent != fRoot) { } // end of list, return null DOM_Node aNull; return aNull; }
void RangeImpl::selectNodeContents(const DOM_Node& node) { validateNode(node); fStartContainer = node; fEndContainer = node; fStartOffset = 0; if (node.getNodeType() == DOM_Node::TEXT_NODE ) { fEndOffset = ((DOM_Text &)node).getLength(); return; } DOM_Node first = node.getFirstChild(); if (first == null) { fEndOffset = 0; return; } unsigned int i = 0; for (DOM_Node n = first; n!=null; n = n.getNextSibling()) { i++; } fEndOffset = i; }
DOMString RangeImpl::toString() const { if( fDetached) { throw DOM_DOMException( DOM_DOMException::INVALID_STATE_ERR, null); } DOM_Node node = fStartContainer; DOM_Node stopNode = fEndContainer; DOMString tempString; if ( (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) || (fStartContainer.getNodeType() == DOM_Node::CDATA_SECTION_NODE) ) { if (fStartContainer == fEndContainer) { tempString.appendData(fStartContainer.getNodeValue().substringData(fStartOffset, fEndOffset-fStartOffset)); return tempString; } else { int length = fStartContainer.getNodeValue().length(); tempString.appendData(fStartContainer.getNodeValue().substringData(fStartOffset, length - fStartOffset)); node = nextNode(node, true); } } else { //fStartContainer is not a TextNode node=node.getFirstChild(); if (fStartOffset>0) { //find a first node within a range, specified by fStartOffset unsigned int counter = 0; while (counter<fStartOffset && node!=null) { node=node.getNextSibling(); counter++; } } if (node == null) { node = nextNode(fStartContainer,false); } } if ( fEndContainer.getNodeType()!= DOM_Node::TEXT_NODE && fEndContainer.getNodeType()!= DOM_Node::CDATA_SECTION_NODE ) { int i=fEndOffset; stopNode = fEndContainer.getFirstChild(); while( i>0 && stopNode!=null ) { --i; stopNode = stopNode.getNextSibling(); } if ( stopNode == null ) stopNode = nextNode( fEndContainer, false ); } while (node != stopNode) { //look into all kids of the Range if (node == null) break; if (node.getNodeType() == DOM_Node::TEXT_NODE || node.getNodeType() == DOM_Node::CDATA_SECTION_NODE) { tempString.appendData(node.getNodeValue()); } node = nextNode(node, true); } if (fEndContainer.getNodeType() == DOM_Node::TEXT_NODE || fEndContainer.getNodeType() == DOM_Node::CDATA_SECTION_NODE) { tempString.appendData(fEndContainer.getNodeValue().substringData(0,fEndOffset)); } return tempString; }