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); }
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; }
/** * Visits the nodes selected by this range when we know * a-priori that the start and end containers are not the * same, but the end container is an ancestor of the start container * */ DOM_DocumentFragment RangeImpl::traverseCommonEndContainer( DOM_Node startAncestor, int how ) { DOM_DocumentFragment frag = null; if ( how!=DELETE_CONTENTS) frag = fDocument.createDocumentFragment(); DOM_Node n = traverseLeftBoundary( startAncestor, how ); if ( frag!=null ) frag.appendChild( n ); int startIdx = indexOf( startAncestor, fEndContainer ); ++startIdx; // Because we already traversed it.... int cnt = fEndOffset - startIdx; n = startAncestor.getNextSibling(); while( cnt > 0 ) { DOM_Node sibling = n.getNextSibling(); DOM_Node xferNode = traverseFullySelected( n, how ); if ( frag!=null ) frag.appendChild( xferNode ); --cnt; n = sibling; } if ( how != CLONE_CONTENTS ) { setStartAfter( startAncestor ); collapse( true ); } return frag; }
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 ); } }
//====================================================================== //====================================================================== 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(); }
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; } }
/** * Traverses the "left 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 left boundary does * not contain the range's end container. * * A "left 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 "left boundary" is the highest subtree node * that contains the starting container. The root of * this subtree is always partially selected. * * In this example, the nodes that are traversed * as "left boundary" nodes are: F, G, and B. * */ DOM_Node RangeImpl::traverseLeftBoundary( DOM_Node root, int how ) { DOM_Node next = getSelectedNode( getStartContainer(), getStartOffset() ); bool isFullySelected = ( next!=getStartContainer() ); if ( next==root ) return traverseNode( next, isFullySelected, true, how ); DOM_Node parent = next.getParentNode(); DOM_Node clonedParent = traverseNode( parent, false, true, how ); while( parent!=null ) { while( next!=null ) { DOM_Node nextSibling = next.getNextSibling(); DOM_Node clonedChild = traverseNode( next, isFullySelected, true, how ); if ( how!=DELETE_CONTENTS ) clonedParent.appendChild(clonedChild); isFullySelected = true; next = nextSibling; } if ( parent==root ) return clonedParent; next = parent.getNextSibling(); parent = parent.getParentNode(); DOM_Node clonedGrandParent = traverseNode( parent, false, true, how ); if ( how!=DELETE_CONTENTS ) clonedGrandParent.appendChild( clonedParent ); clonedParent = clonedGrandParent; } // should never occur return null; }
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; }
/** * Visits the nodes selected by this range when we know * a-priori that the start and end containers are not * the same, and we also know that neither the start * nor end container is an ancestor of the other. */ DOM_DocumentFragment RangeImpl::traverseCommonAncestors( DOM_Node startAncestor, DOM_Node endAncestor, int how ) { DOM_DocumentFragment frag = null; if ( how!=DELETE_CONTENTS) frag = fDocument.createDocumentFragment(); DOM_Node n = traverseLeftBoundary( startAncestor, how ); if ( frag!=null ) frag.appendChild( n ); DOM_Node commonParent = startAncestor.getParentNode(); int startOffset = indexOf( startAncestor, commonParent ); int endOffset = indexOf( endAncestor, commonParent ); ++startOffset; int cnt = endOffset - startOffset; DOM_Node sibling = startAncestor.getNextSibling(); while( cnt > 0 ) { DOM_Node nextSibling = sibling.getNextSibling(); n = traverseFullySelected( sibling, how ); if ( frag!=null ) frag.appendChild( n ); sibling = nextSibling; --cnt; } n = traverseRightBoundary( endAncestor, how ); if ( frag!=null ) frag.appendChild( n ); if ( how != CLONE_CONTENTS ) { setStartAfter( startAncestor ); collapse( true ); } return frag; }
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; }
/** This is the master routine invoked to visit the nodes * selected by this range. For each such node, different * actions are taken depending on the value of the TraversalType argument. */ DOM_DocumentFragment RangeImpl::traverseContents(TraversalType how) { if (fDetached) throw DOM_DOMException(DOM_DOMException::INVALID_STATE_ERR, null); if (fStartContainer == null || fEndContainer == null) { return DOM_DocumentFragment(); // REVIST: Throw exception? } /* Traversal is accomplished by first determining the relationship between the endpoints of the range. For each of four significant relationships, we will delegate the traversal call to a method that can make appropriate assumptions. */ // case 1: same container if ( fStartContainer == fEndContainer ) return traverseSameContainer( how ); // case 2: Child C of start container is ancestor of end container for (DOM_Node node = fStartContainer.getFirstChild(); node != null; node=node.getNextSibling()) { if (isAncestorOf(node, fEndContainer)) return traverseCommonStartContainer( node, how ); } // case 3: Child C of end container is ancestor of start container for (DOM_Node nd = fEndContainer.getFirstChild(); nd != null; nd=nd.getNextSibling()) { if (isAncestorOf(nd, fStartContainer)) return traverseCommonEndContainer( nd, how ); } // case 4: preorder traversal of context tree. // There is a common ancestor container. Find the // ancestor siblings that are children of that container. DOM_Node ancestor = commonAncestorOf(fStartContainer, fEndContainer); return traverseCommonAncestors( ancestor, ancestor, how ); }
/** * Visits the nodes selected by this range when we know * a-priori that the start and end containers are the same. * */ DOM_DocumentFragment RangeImpl::traverseSameContainer( int how ) { DOM_DocumentFragment frag = null; if ( how!=DELETE_CONTENTS) frag = fDocument.createDocumentFragment(); // If selection is empty, just return the fragment if ( fStartOffset==fEndOffset ) return frag; DOM_Node current = fStartContainer; DOM_Node cloneCurrent = null; // Text node needs special case handling if ( fStartContainer.getNodeType()== DOM_Node::TEXT_NODE ) { cloneCurrent = fStartContainer.cloneNode(false); cloneCurrent.setNodeValue( cloneCurrent.getNodeValue().substringData(fStartOffset, fEndOffset - fStartOffset)); // set the original text node to its new value if ( how != CLONE_CONTENTS ) ((DOM_Text &)fStartContainer).deleteData(fStartOffset, fEndOffset-fStartOffset); if ( how != DELETE_CONTENTS) frag.appendChild(cloneCurrent); } else { // Copy nodes between the start/end offsets. DOM_Node n = getSelectedNode( fStartContainer, fStartOffset ); int cnt = fEndOffset - fStartOffset; while( cnt > 0 ) { DOM_Node sibling = n.getNextSibling(); DOM_Node xferNode = traverseFullySelected( n, how ); if ( frag!=null ) frag.appendChild( xferNode ); --cnt; n = sibling; } } // Nothing is partially selected, so collapse to start point if ( how != CLONE_CONTENTS ) collapse(true); return frag; }
/** * 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 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 TreeWalkerImpl::getNextSibling (DOM_Node node) { DOM_Node result; if (node.isNull() || node == fRoot) return result; DOM_Node newNode = node.getNextSibling(); if (newNode.isNull()) { newNode = node.getParentNode(); if (newNode.isNull() || node == fRoot) return result; short parentAccept = acceptNode(newNode); if (parentAccept == DOM_NodeFilter::FILTER_SKIP) { return getNextSibling(newNode); } return result; } short accept = acceptNode(newNode); if (accept == DOM_NodeFilter::FILTER_ACCEPT) return newNode; else if (accept == DOM_NodeFilter::FILTER_SKIP) { DOM_Node fChild = getFirstChild(newNode); if (fChild.isNull()) { return getNextSibling(newNode); } return fChild; } return getNextSibling(newNode); }
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; }
Components::ConfigValues* Properties::getConfigValues() { char* fileName = strdup( descriptor_.c_str() ); parser_->parse( fileName ); document_ = parser_->getDocument(); DOM_Element property = document_.getDocumentElement(); Components::ConfigValues* config = new Components::ConfigValues(); int len = 0; DOM_Node child = property.getFirstChild(); while( child != 0) { // simple if( ( child.getNodeType() == DOM_Node::ELEMENT_NODE ) && ( child.getNodeName().equals( "simple" ) ) ) { DOM_NodeList nodeList; DOM_Element simple = ( DOM_Element& )child; std::string type = simple.getAttribute( "type" ).transcode(); std::string name = simple.getAttribute( "name" ).transcode(); nodeList = simple.getElementsByTagName( "value" ); DOM_Element value = ( const DOM_Element& )nodeList.item( 0 ); CORBA::Any any; std::string val = value.getFirstChild().getNodeValue().transcode(); if( type == "boolean" ) { CORBA::Boolean v; if( val == "true" ) { v = true; } else { v = false; } any <<= CORBA::Any::from_boolean( v ); } if( type == "char" ) { CORBA::Char v = val[0]; any <<= CORBA::Any::from_char( v ); } if( type == "double" ) { CORBA::Double v = atof( val.c_str() ); any <<= v; } if( type == "float" ) { CORBA::Float v = atof( val.c_str() ); any <<= v; } if( type == "short" ) { CORBA::Short v = atoi( val.c_str() ); any <<= v; } if( type == "long" ) { CORBA::Long v = atol( val.c_str() ); any <<= v; } if( type == "objref" ) { // TODO } if( type == "octet" ) { CORBA::Octet v = val[0]; any <<= CORBA::Any::from_octet( v ); } if( type == "string" ) { any <<= val.c_str(); } if( type == "ulong" ) { CORBA::ULong v = atol( val.c_str() ); any <<= v; } if( type == "ushort" ) { CORBA::UShort v = atol( val.c_str() ); any <<= v; } // new config entry config->length( ++len ); ( *config )[len - 1] = new ConfigValue_impl( CORBA::string_dup( name.c_str() ), any ); } // sequence if( ( child.getNodeType() == DOM_Node::ELEMENT_NODE ) && ( child.getNodeName().equals( "sequence" ) ) ) { } // struct if( ( child.getNodeType() == DOM_Node::ELEMENT_NODE ) && ( child.getNodeName().equals( "struct" ) ) ) { } // value if( ( child.getNodeType() == DOM_Node::ELEMENT_NODE ) && ( child.getNodeName().equals( "valuetype" ) ) ) { } // next element child = child.getNextSibling(); } return config; }
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; }
void RangeImpl::insertNode(DOM_Node& newNode) { if (newNode == null) return; //don't have to do anything for (DOM_Node aNode = fStartContainer; aNode!=null; aNode = aNode.getParentNode()) { if (aNode.fImpl->isReadOnly()) { throw DOM_DOMException( DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null); } } if (fDocument != newNode.getOwnerDocument()) { throw DOM_DOMException( DOM_DOMException::WRONG_DOCUMENT_ERR, null); } // Prevent cycles in the tree. //isKidOK() is not checked here as its taken care by insertBefore() function if (isAncestorOf( newNode, fStartContainer)) { throw DOM_DOMException( DOM_DOMException::HIERARCHY_REQUEST_ERR, null); } if( fDetached) { throw DOM_DOMException( DOM_DOMException::INVALID_STATE_ERR, null); } int type = newNode.getNodeType(); if (type == DOM_Node::ATTRIBUTE_NODE || type == DOM_Node::ENTITY_NODE || type == DOM_Node::NOTATION_NODE || type == DOM_Node::DOCUMENT_NODE) { throw DOM_RangeException( DOM_RangeException::INVALID_NODE_TYPE_ERR, null); } DOM_Node parent; DOM_Node next; if (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) { //set 'parent' and 'next' here parent = fStartContainer.getParentNode(); //split the text nodes if (fStartOffset > 0) ((DOM_Text &)fStartContainer).splitText(fStartOffset); //update the new start information later. After inserting the first newNode if (fStartOffset == 0) next = fStartContainer; else next = fStartContainer.getNextSibling(); } // end of text handling else { parent = fStartContainer; next = fStartContainer.getFirstChild(); for(unsigned int i = 0; (i < fStartOffset) && (next != null); i++) { next=next.getNextSibling(); } } if (parent != null) { if (next != null) parent.insertBefore(newNode, next); else parent.appendChild(newNode); } }
short RangeImpl::compareBoundaryPoints(DOM_Range::CompareHow how, RangeImpl* srcRange) const { if (fDocument != srcRange->fDocument) { throw DOM_DOMException( DOM_DOMException::WRONG_DOCUMENT_ERR, null); } if( fDetached) { throw DOM_DOMException( DOM_DOMException::INVALID_STATE_ERR, null); } DOM_Node pointA, pointB; int offsetA, offsetB; switch (how) { case (DOM_Range::START_TO_START) : pointB = srcRange->getStartContainer(); pointA = fStartContainer; offsetB = srcRange->getStartOffset(); offsetA = fStartOffset; break; case (DOM_Range::START_TO_END) : pointB = srcRange->getStartContainer(); pointA = fEndContainer; offsetB = srcRange->getStartOffset(); offsetA = fEndOffset; break; case (DOM_Range::END_TO_START) : pointB = srcRange->getEndContainer(); pointA = fStartContainer; offsetB = srcRange->getEndOffset(); offsetA = fStartOffset; break; case (DOM_Range::END_TO_END) : pointB = srcRange->getEndContainer(); pointA = fEndContainer; offsetB = srcRange->getEndOffset(); offsetA = fEndOffset; break; default: throw DOM_DOMException( DOM_DOMException::INVALID_STATE_ERR, null); } // case 1: same container if (pointA == pointB) { if (offsetA < offsetB) return -1; //A before B if (offsetA == offsetB) return 0; //A equal to B return 1; // A after B } // case 2: Child C of container A is ancestor of B for (DOM_Node node = pointA.getFirstChild(); node != null; node=node.getNextSibling()) { if (isAncestorOf(node, pointB)) { int index = indexOf(node, pointA); if (offsetA <= index) return -1; return 1; } } // case 3: Child C of container B is ancestor of A for (DOM_Node nd = pointB.getFirstChild(); nd != null; nd=nd.getNextSibling()) { if (isAncestorOf(nd, pointA)) { int index = indexOf(nd, pointB); if (index < offsetB ) return -1; return 1; //B strictly before A } } // case 4: preorder traversal of context tree. DOM_Node ancestor = commonAncestorOf(pointA, pointB); DOM_Node current = ancestor; do { if (current == pointA) return -1; if (current == pointB) return 1; current = nextNode(current, true); } while (current!=null && current!=ancestor); return -2; // this should never happen }
char* XMLDocument::encode(DOM_Node currNode) { string result = ""; if (currNode == NULL) return strclone((char*)result.c_str()); switch (currNode.getNodeType()) { case DOM_Node::ELEMENT_NODE: { char* tmp = currNode.getNodeName().transcode(); result += (string)"<" + (string)tmp; delete[] tmp; DOM_NamedNodeMap nnodeMap = currNode.getAttributes(); for (unsigned int i = 0; i < nnodeMap.getLength(); i++) { DOM_Node attNode = nnodeMap.item(i); tmp = attNode.getNodeName().transcode(); char* tmp1 = attNode.getNodeValue().transcode(); result += (string)" " + (string)tmp + (string)"=\"" + (string)tmp1 + (string)"\""; delete[] tmp; delete[] tmp1; } result += (string)">"; DOM_Node child = currNode.getFirstChild(); while (child != NULL) { char *childStr = encode(child); result += childStr; delete[] childStr; child = child.getNextSibling(); } tmp = currNode.getNodeName().transcode(); result += (string)"</" + (string)tmp + ">"; delete[] tmp; return strclone((char*)result.c_str()); } case DOM_Node::TEXT_NODE: case DOM_Node::CDATA_SECTION_NODE: { static char reservedChars[] = "<>&'\""; char *str = currNode.getNodeValue().transcode(); bool bSpecialChars = false; int len = strlen(str); for (int i = 0; i < len; i++) { if (strchr(reservedChars, str[i]) != NULL) { bSpecialChars = true; break; } } if (bSpecialChars == false) result += (string)str; else result += (string)"<![CDATA[" + (string)str + (string)"]]>"; delete[] str; return strclone((char*)result.c_str()); } default: { return strclone((char*)result.c_str()); } } }
// --------------------------------------------------------------------------- // ostream << DOM_Node // // Stream out a DOM node, and, recursively, all of its children. This // function is the heart of writing a DOM tree out as XML source. Give it // a document node and it will do the whole thing. // --------------------------------------------------------------------------- ostream& operator<<(ostream& target, DOM_Node& toWrite) { // Get the name and value out for convenience DOMString nodeName = toWrite.getNodeName(); DOMString nodeValue = toWrite.getNodeValue(); unsigned long lent = nodeValue.length(); switch (toWrite.getNodeType()) { case DOM_Node::TEXT_NODE: { gFormatter->formatBuf(nodeValue.rawBuffer(), lent, XMLFormatter::CharEscapes); break; } case DOM_Node::PROCESSING_INSTRUCTION_NODE : { *gFormatter << XMLFormatter::NoEscapes << gStartPI << nodeName; if (lent > 0) { *gFormatter << chSpace << nodeValue; } *gFormatter << XMLFormatter::NoEscapes << gEndPI; break; } case DOM_Node::DOCUMENT_NODE : { DOM_Node child = toWrite.getFirstChild(); while( child != 0) { target << child; // add linefeed in requested output encoding *gFormatter << chLF; target << flush; child = child.getNextSibling(); } break; } case DOM_Node::ELEMENT_NODE : { // The name has to be representable without any escapes *gFormatter << XMLFormatter::NoEscapes << chOpenAngle << nodeName; // Output the element start tag. // Output any attributes on this element DOM_NamedNodeMap attributes = toWrite.getAttributes(); int attrCount = attributes.getLength(); for (int i = 0; i < attrCount; i++) { DOM_Node attribute = attributes.item(i); // // Again the name has to be completely representable. But the // attribute can have refs and requires the attribute style // escaping. // *gFormatter << XMLFormatter::NoEscapes << chSpace << attribute.getNodeName() << chEqual << chDoubleQuote << XMLFormatter::AttrEscapes << attribute.getNodeValue() << XMLFormatter::NoEscapes << chDoubleQuote; } // // Test for the presence of children, which includes both // text content and nested elements. // DOM_Node child = toWrite.getFirstChild(); if (child != 0) { // There are children. Close start-tag, and output children. // No escapes are legal here *gFormatter << XMLFormatter::NoEscapes << chCloseAngle; while( child != 0) { target << child; child = child.getNextSibling(); } // // Done with children. Output the end tag. // *gFormatter << XMLFormatter::NoEscapes << gEndElement << nodeName << chCloseAngle; } else { // // There were no children. Output the short form close of // the element start tag, making it an empty-element tag. // *gFormatter << XMLFormatter::NoEscapes << chForwardSlash << chCloseAngle; } break; } case DOM_Node::ENTITY_REFERENCE_NODE: { DOM_Node child; #if 0 for (child = toWrite.getFirstChild(); child != 0; child = child.getNextSibling()) { target << child; } #else // // Instead of printing the refernece tree // we'd output the actual text as it appeared in the xml file. // This would be the case when -e option was chosen // *gFormatter << XMLFormatter::NoEscapes << chAmpersand << nodeName << chSemiColon; #endif break; } case DOM_Node::CDATA_SECTION_NODE: { *gFormatter << XMLFormatter::NoEscapes << gStartCDATA << nodeValue << gEndCDATA; break; } case DOM_Node::COMMENT_NODE: { *gFormatter << XMLFormatter::NoEscapes << gStartComment << nodeValue << gEndComment; break; } case DOM_Node::DOCUMENT_TYPE_NODE: { DOM_DocumentType doctype = (DOM_DocumentType &)toWrite;; *gFormatter << XMLFormatter::NoEscapes << gStartDoctype << nodeName; DOMString id = doctype.getPublicId(); if (id != 0) { *gFormatter << XMLFormatter::NoEscapes << chSpace << gPublic << id << chDoubleQuote; id = doctype.getSystemId(); if (id != 0) { *gFormatter << XMLFormatter::NoEscapes << chSpace << chDoubleQuote << id << chDoubleQuote; } } else { id = doctype.getSystemId(); if (id != 0) { *gFormatter << XMLFormatter::NoEscapes << chSpace << gSystem << id << chDoubleQuote; } } id = doctype.getInternalSubset(); if (id !=0) *gFormatter << XMLFormatter::NoEscapes << chOpenSquare << id << chCloseSquare; *gFormatter << XMLFormatter::NoEscapes << chCloseAngle; break; } case DOM_Node::ENTITY_NODE: { *gFormatter << XMLFormatter::NoEscapes << gStartEntity << nodeName; DOMString id = ((DOM_Entity &)toWrite).getPublicId(); if (id != 0) *gFormatter << XMLFormatter::NoEscapes << gPublic << id << chDoubleQuote; id = ((DOM_Entity &)toWrite).getSystemId(); if (id != 0) *gFormatter << XMLFormatter::NoEscapes << gSystem << id << chDoubleQuote; id = ((DOM_Entity &)toWrite).getNotationName(); if (id != 0) *gFormatter << XMLFormatter::NoEscapes << gNotation << id << chDoubleQuote; *gFormatter << XMLFormatter::NoEscapes << chCloseAngle << chLF; break; } case DOM_Node::XML_DECL_NODE: { DOMString str; *gFormatter << gXMLDecl1 << ((DOM_XMLDecl &)toWrite).getVersion(); *gFormatter << gXMLDecl2 << gEncodingName; str = ((DOM_XMLDecl &)toWrite).getStandalone(); if (str != 0) *gFormatter << gXMLDecl3 << str; *gFormatter << gXMLDecl4; break; } default: cerr << "Unrecognized node type = " << (long)toWrite.getNodeType() << endl; } return target; }