void XercesUpdateFactory::removeType(DOMNode *node) { DOMNode *ancestor = node; // 1. If $N is an element node, its properties are changed as follows: if(node->getNodeType() == DOMNode::ELEMENT_NODE) { // a. If type-name is not equal to xs:untyped, then const XMLCh *typeURI, *typeName; XercesNodeImpl::typeUriAndName(node, typeURI, typeName); if(!XPath2Utils::equals(typeName, DocumentCache::g_szUntyped) || !XPath2Utils::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { // i. type-name is set to xs:anyType XercesSequenceBuilder::setElementTypeInfo((DOMElement *)node, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, SchemaSymbols::fgATTVAL_ANYTYPE); // ii. If the parent of N is an element node, then upd:removeType(parent($N)) is invoked. DOMNode *parent = node->getParentNode(); if(parent && parent->getNodeType() == DOMNode::ELEMENT_NODE) removeType(parent); } // b. string-value is set equal to the concatenated contents of the text node descendants, in document order. // c. typed-value is set equal to the string-value property, as an instance of xs:untypedAtomic. // d. nilled, is-id, and is-idrefs are set to false. // Automatically done by changing the type } // 2. If $N is an attribute node, its properties are changed as follows: else if(node->getNodeType() == DOMNode::ATTRIBUTE_NODE) { // a. type-name is set to xs:untypedAtomic. XercesSequenceBuilder::setAttributeTypeInfo((DOMAttr *)node, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, ATUntypedAtomic::fgDT_UNTYPEDATOMIC); // b. typed-value is set equal to the string-value property, as an instance of xs:untypedAtomic. // c. is-id and is-idrefs are set to false. // Automatically done by changing the type // d. If $N has a parent, upd:removeType(parent($N)) is invoked. ancestor = ((DOMAttr*)node)->getOwnerElement(); if(ancestor) removeType(ancestor); } else return; // 3. The topmost ancestor of $N is marked for revalidation. if(ancestor) { while(ancestor->getParentNode() != 0) ancestor = ancestor->getParentNode(); forRevalidation_.insert(ancestor); } }
void XercesUpdateFactory::applyRename(const PendingUpdate &update, DynamicContext *context) { const XercesNodeImpl *nodeImpl = (const XercesNodeImpl*)update.getTarget()->getInterface(Item::gXQilla); DOMNode *domnode = const_cast<DOMNode*>(nodeImpl->getDOMNode()); ATQNameOrDerived *qname = (ATQNameOrDerived*)update.getValue().first().get(); if(domnode->getNodeType() == DOMNode::PROCESSING_INSTRUCTION_NODE) { DOMProcessingInstruction *newPI = domnode->getOwnerDocument()-> createProcessingInstruction(qname->getName(), domnode->getNodeValue()); domnode->getParentNode()->replaceChild(newPI, domnode); domnode = newPI; } else { // If $newName has an implied namespace binding that conflicts with an existing namespace binding // in the namespaces property of $target, a dynamic error is raised [err:XUDY0024]. // If $target has a parent, and $newName has an implied namespace binding that conflicts with a // namespace binding in the namespaces property of parent($target), a dynamic error is raised [err:XUDY0024]. domnode->getOwnerDocument()->renameNode(domnode, qname->getURI(), qname->getName()); if(qname->getURI() != 0 && *qname->getURI() != 0) domnode->setPrefix(qname->getPrefix()); removeType(domnode); } // Deliberately create a new XercesNodeImpl, since the PI is actually // replaced, not just renamed, meaning it is no longer attached to the tree addToPutSet(nodeImpl, &update, context); }
void XercesUpdateFactory::completeDeletions(DynamicContext *context) { // e. Finally, for each node marked for deletion by one of the update primitives listed above, let $N be the node that is marked // for deletion, and let $P be its parent node. The following actions are applied: // i. The parent property of $N is set to empty. // ii. If $N is an attribute node, the attributes property of $P is modified to remove $N. // iii. If $N is a non-attribute node, the children property of $P is modified to remove $N. // iv. If $N is an element, attribute, or text node, and $P is an element node, then upd:removeType($P) is invoked. for(DOMNodeSet::iterator i = forDeletion_.begin(); i != forDeletion_.end(); ++i) { DOMNode *domnode = *i; if(domnode->getNodeType() == DOMNode::ATTRIBUTE_NODE) { DOMAttr *attr = (DOMAttr*)domnode; DOMElement *owner = attr->getOwnerElement(); if(owner != 0) { owner->removeAttributeNode(attr); removeType(owner); } } else { DOMNode *parent = domnode->getParentNode(); if(parent != 0) { parent->removeChild(domnode); if(domnode->getNodeType() == DOMNode::ELEMENT_NODE || domnode->getNodeType() == DOMNode::TEXT_NODE || domnode->getNodeType() == DOMNode::CDATA_SECTION_NODE) { removeType(parent); } } } } }
bool TXFMXPathFilter::checkNodeInInput(DOMNode * n, DOMNode * attParent) { if (mp_fragment != NULL) { DOMNode * p = n; /* Check attParent here to reduce cycles */ if (attParent != NULL) { if (p == mp_fragment) return true; p = attParent; } while (p != NULL) { if (p == mp_fragment) return true; p = p->getParentNode(); } return false; } return mp_inputList->hasNode(n); }
const XMLCh* DOMNodeImpl::getBaseURI() const{ DOMNode *thisNode = castToNode(this); DOMNode* parent = thisNode->getParentNode(); if (parent) return parent->getBaseURI(); else return 0; }
/** Return node, if matches or any parent if matches. */ DOMNode* DOMNodeIteratorImpl::matchNodeOrParent (DOMNode* node) { for (DOMNode* n = fCurrentNode; n != fRoot; n = n->getParentNode()) { if (node == n) return n; } return 0; }
//Detect field name of value element static char* fieldName(DOMElement* elem) { DOMNode *node = elem; if (getGeometryTypeOfElem(elem)) { int depth = 0; // Depth of value elem node for (node = elem; node; node = node->getParentNode()) ++depth; //Field name is on level 4 node = elem; for (int d = 0; d<depth-4; ++d) node = node->getParentNode(); } if( node == NULL ) { CPLError(CE_Failure, CPLE_AssertionFailed, "node == NULL"); return CPLStrdup("***bug***"); } char* pszNodeName = tr_strdup(node->getNodeName()); return pszNodeName; }
DOMNode* DOMNodeImpl::getElementAncestor (const DOMNode* currentNode) const { DOMNode* parent = currentNode->getParentNode(); while(parent != 0) { short type = parent->getNodeType(); if (type == DOMNode::ELEMENT_NODE) { return parent; } parent=parent->getParentNode(); } return 0; }
void DeltaApplyEngine::Subtree_Delete( const char *xidmapStr ) { XidMap_Parser parse(xidmapStr) ; // Note here that the PostFix order for XID-map is important to garantuee that nodes will be deleted in the correct order while (!parse.isListEmpty()) { XID_t deleteXID = parse.getNextXID(); vddprintf(( " delete node xid=%d\n", (int) deleteXID )); DOMNode* deleteNode = xiddoc->getXidMap().getNodeWithXID( deleteXID ); if (deleteNode==NULL) THROW_AWAY(("node with XID=%d not found",(int)deleteXID)); xiddoc->getXidMap().removeNode( deleteNode ); deleteNode = deleteNode->getParentNode()->removeChild( deleteNode ); } }
void DeltaApplyEngine::Subtree_MoveFrom( XID_t myXID ) { vddprintf((" move (from) node xid=%d\n", (int) myXID )); DOMNode* moveNode = xiddoc->getXidMap().getNodeWithXID( myXID ); if (moveNode==NULL) THROW_AWAY(("node with XID=%d not found",(int)myXID)); DOMNode* backupNode = moveDocument->importNode( moveNode, true ); moveDocument->getXidMap().mapSubtree( xiddoc->getXidMap().String(moveNode).c_str() , backupNode ); moveDocument->getDocumentElement()->appendChild( backupNode ); moveNode = moveNode->getParentNode()->removeChild( moveNode ); xiddoc->getXidMap().removeSubtree( moveNode ); }
char* fieldName(DOMElement* elem) { string fullname; int depth = 0; DOMNode *node; for (node = elem; node; node = node->getParentNode()) ++depth; depth-=3; //ignore root elements // We cannot do this sort of dynamic stack alloc on MSVC6. // DOMNode* elements[depth]; DOMNode* elements[1000]; CPLAssert( depth < (int)(sizeof(elements) / sizeof(DOMNode*)) ); int d=0; for (node = elem; d<depth; node = node->getParentNode()) elements[d++] = node; for (d=depth-1; d>=0; --d) { if (d < depth-1) fullname += "_"; char* pszNodeName = XMLString::transcode(elements[d]->getNodeName()); fullname += pszNodeName; XMLString::release(&pszNodeName); } return CPLStrdup(fullname.c_str()); }
void DeltaApplyEngine::Subtree_MoveTo( XID_t myXID, XID_t parentXID, int position ) { vddprintf((" move subtree rooted by %d to (parent=%d, pos=%d)\n", (int)myXID, (int)parentXID, position)); DOMNode* moveRoot = NULL; try { moveRoot = moveDocument->getXidMap().getNodeWithXID( myXID ) ; } catch (...) { return; } if (moveRoot==NULL) return; //THROW_AWAY(("node with XID=%d not found",(int)myXID)); Subtree_Insert(moveRoot, parentXID, position, moveDocument->getXidMap().String(moveRoot).c_str() ); (void)moveRoot->getParentNode()->removeChild(moveRoot); }
void XercesUpdateFactory::applyReplaceValue(const PendingUpdate &update, DynamicContext *context) { const XercesNodeImpl *nodeImpl = (const XercesNodeImpl*)update.getTarget()->getInterface(Item::gXQilla); DOMNode *domnode = const_cast<DOMNode*>(nodeImpl->getDOMNode()); // 2. If $target is a text, comment, or processing instruction node: content of $target is set to $string-value. domnode->setNodeValue(update.getValue().first()->asString(context)); if(domnode->getNodeType() == DOMNode::ATTRIBUTE_NODE) { // 1. If $target is an attribute node: // a. string-value of $target is set to $string-value. (done above) // b. upd:removeType($target) is invoked. removeType(domnode); } else if(domnode->getNodeType() == DOMNode::TEXT_NODE || domnode->getNodeType() == DOMNode::CDATA_SECTION_NODE) { // 3. If $target is a text node, upd:removeType(parent($target)) is invoked. if(domnode->getParentNode() != 0) removeType(domnode->getParentNode()); } addToPutSet(update.getTarget(), &update, context); }
// Returns the previous logical sibling with respect to the given node. DOMNode* DOMElementImpl::getPreviousLogicalSibling(const DOMNode* n) const { DOMNode* prev = n->getPreviousSibling(); // If "n" has no previous sibling and its parent is an entity reference node we // need to continue the search through the previous siblings of the entity // reference as these are logically siblings of the given node. if (prev == NULL) { DOMNode* parent = n->getParentNode(); while (parent != NULL && parent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) { prev = parent->getPreviousSibling(); if (prev != NULL) { break; } parent = parent->getParentNode(); } } return prev; }
void XercesUpdateFactory::applyInsertAfter(const PendingUpdate &update, DynamicContext *context) { const XercesNodeImpl *nodeImpl = (const XercesNodeImpl*)update.getTarget()->getInterface(Item::gXQilla); DOMNode *domnode = const_cast<DOMNode*>(nodeImpl->getDOMNode()); DOMNode *before = domnode->getNextSibling(); Node::Ptr parentNode = nodeImpl->dmParent(context); DOMNode *parent = domnode->getParentNode(); DOMDocument *doc = const_cast<DOMDocument*>(XPath2Utils::getOwnerDoc(domnode)); bool untyped = parentNode->dmNodeKind() == Node::element_string && XPath2Utils::equals(parentNode->getTypeName(), DocumentCache::g_szUntyped) && XPath2Utils::equals(parentNode->getTypeURI(), SchemaSymbols::fgURI_SCHEMAFORSCHEMA); bool containsElementOrText = false; Result children = update.getValue(); Item::Ptr item; while((item = children->next(context)).notNull()) { const XercesNodeImpl *childImpl = (const XercesNodeImpl*)item->getInterface(Item::gXQilla); DOMNode *newChild = importNodeFix(doc, const_cast<DOMNode*>(childImpl->getDOMNode()), /*deep*/true); if(childImpl->dmNodeKind() == Node::element_string || childImpl->dmNodeKind() == Node::text_string) { containsElementOrText = true; } // If the type-name property of parent($target) is xs:untyped, then upd:setToUntyped() is invoked on each // element or attribute node in $content. if(!untyped) setTypes(newChild, childImpl->getDOMNode()); // For each node in $content, the parent property is set to parent($target). // The children property of parent($target) is modified to add the nodes in $content just before $target, // preserving their order. parent->insertBefore(newChild, before); } // If at least one of the nodes in $content is an element or text node, upd:removeType(parent($target)) is invoked. if(containsElementOrText) { removeType(parent); } addToPutSet(update.getTarget(), &update, context); }
DOMNode *WrapXerces::getNextLogicalSibling ( const DOMNode* n ) { // Copied from Xerces-C DOMNode* next = n->getNextSibling(); // If "n" has no following sibling and its parent is an entity reference node we // need to continue the search through the following siblings of the entity // reference as these are logically siblings of the given node. if ( !next ) { DOMNode* parent = n->getParentNode(); while ( parent && parent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE ) { next = parent->getNextSibling(); if ( next ) break; parent = parent->getParentNode(); } } return next; }
DOMNode* DOMNodeIteratorImpl::nextNode (DOMNode* node, bool visitChildren) { if (fDetached) throw DOMException(DOMException::INVALID_STATE_ERR, 0, GetDOMNodeIteratorMemoryManager); if (!node) return fRoot; DOMNode* result = 0; // only check children if we visit children. if (visitChildren) { //if hasChildren, return 1st child. if ((fExpandEntityReferences || node->getNodeType()!=DOMNode::ENTITY_REFERENCE_NODE) && node->hasChildNodes()) { result = node->getFirstChild(); return result; } } // if hasSibling, return sibling if (node != fRoot) { result = node->getNextSibling(); if (result != 0) return result; // return parent's 1st sibling. DOMNode* parent = node->getParentNode(); while ((parent != 0) && parent != fRoot) { result = parent->getNextSibling(); if (result != 0) { return result; } else { parent = parent->getParentNode(); } } // while (parent != 0 && parent != fRoot) { } // end of list, return 0 return 0; }
void XercesUpdateFactory::applyReplaceNode(const PendingUpdate &update, DynamicContext *context) { const XercesNodeImpl *nodeImpl = (const XercesNodeImpl*)update.getTarget()->getInterface(Item::gXQilla); DOMNode *domnode = const_cast<DOMNode*>(nodeImpl->getDOMNode()); Node::Ptr parentNode = nodeImpl->dmParent(context); DOMNode *parent = domnode->getParentNode(); DOMDocument *doc = const_cast<DOMDocument*>(XPath2Utils::getOwnerDoc(domnode)); bool untyped = parentNode->dmNodeKind() == Node::element_string && XPath2Utils::equals(parentNode->getTypeName(), DocumentCache::g_szUntyped) && XPath2Utils::equals(parentNode->getTypeURI(), SchemaSymbols::fgURI_SCHEMAFORSCHEMA); Result children = update.getValue(); Item::Ptr item; while((item = children->next(context)).notNull()) { const XercesNodeImpl *childImpl = (const XercesNodeImpl*)item->getInterface(Item::gXQilla); DOMNode *newChild = importNodeFix(doc, const_cast<DOMNode*>(childImpl->getDOMNode()), /*deep*/true); // 1b. If the type-name property of parent($target) is xs:untyped, then upd:setToUntyped() is invoked // on each element node in $replacement. if(!untyped) setTypes(newChild, childImpl->getDOMNode()); // 1a. For each node in $replacement, the parent property is set to parent($target). // 3b. If $target is an element, text, comment, or processing instruction node, the children property // of parent($target) is modified to add the nodes in $replacement just before $target, preserving // their order. parent->insertBefore(newChild, domnode); } // 2a. $target is marked for deletion. forDeletion_.insert(domnode); // 3c. upd:removeType(parent($target)) is invoked. removeType(parent); addToPutSet(update.getTarget(), &update, context); }
DOMText* DOMTextImpl::replaceWholeText(const XMLCh* newText) { DOMDocument *doc = getOwnerDocument(); DOMTreeWalker* pWalker=doc->createTreeWalker(doc->getDocumentElement(), DOMNodeFilter::SHOW_ALL, NULL, true); pWalker->setCurrentNode((DOMNode*)this); // Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in // reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes. DOMNode* pFirstTextNode=this; DOMNode* prevNode; while((prevNode=pWalker->previousNode())!=NULL) { if(prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) break; pFirstTextNode=prevNode; } // before doing any change we need to check if we are going to remove an entity reference that doesn't contain just text DOMNode* pCurrentNode=pWalker->getCurrentNode(); DOMNode* nextNode; while((nextNode=pWalker->nextNode())!=NULL) { if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) break; if(nextNode->getNodeType()==ENTITY_REFERENCE_NODE) { DOMTreeWalker* pInnerWalker=doc->createTreeWalker(nextNode, DOMNodeFilter::SHOW_ALL, NULL, true); while(pInnerWalker->nextNode()) { short nodeType=pInnerWalker->getCurrentNode()->getNodeType(); if(nodeType!=ENTITY_REFERENCE_NODE && nodeType!=TEXT_NODE && nodeType!=CDATA_SECTION_NODE) throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); } pInnerWalker->release(); } } DOMText* retVal=NULL; // if the first node in the chain is a text node, replace its content, otherwise create a new node if(newText && *newText) { if(!castToNodeImpl(pFirstTextNode)->isReadOnly() && (pFirstTextNode->getNodeType()==TEXT_NODE || pFirstTextNode->getNodeType()==CDATA_SECTION_NODE)) { pFirstTextNode->setNodeValue(newText); retVal=(DOMText*)pFirstTextNode; } else { if(getNodeType()==TEXT_NODE) retVal=doc->createTextNode(newText); else retVal=doc->createCDATASection(newText); pFirstTextNode->getParentNode()->insertBefore(retVal, pFirstTextNode); } } // now delete all the following text nodes pWalker->setCurrentNode(pCurrentNode); while((nextNode=pWalker->nextNode())!=NULL) { if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE) break; if(nextNode!=retVal) { // keep the tree walker valid pWalker->previousNode(); nextNode->getParentNode()->removeChild(nextNode); nextNode->release(); } } pWalker->release(); return retVal; }
short DOMNodeImpl::compareTreePosition(const DOMNode* other) const { // Questions of clarification for this method - to be answered by the // DOM WG. Current assumptions listed - LM // // 1. How do ENTITY nodes compare? // Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes // aren't really 'in the tree' // // 2. How do NOTATION nodes compare? // Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes // aren't really 'in the tree' // // 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT // only relevant for nodes that are "part of the document tree"? // <outer> // <inner myattr="true"/> // </outer> // Is the element node "outer" considered an ancestor of "myattr"? // Current assumption: No. // // 4. How do children of ATTRIBUTE nodes compare (with eachother, or // with children of other attribute nodes with the same element) // Current assumption: Children of ATTRIBUTE nodes are treated as if // they are the attribute node itself, unless the 2 nodes // are both children of the same attribute. // // 5. How does an ENTITY_REFERENCE node compare with it's children? // Given the DOM, it should precede its children as an ancestor. // Given "document order", does it represent the same position? // Current assumption: An ENTITY_REFERENCE node is an ancestor of its // children. // // 6. How do children of a DocumentFragment compare? // Current assumption: If both nodes are part of the same document // fragment, there are compared as if they were part of a document. DOMNode* thisNode = castToNode(this); // If the nodes are the same... if (thisNode == other) return (DOMNode::TREE_POSITION_SAME_NODE | DOMNode::TREE_POSITION_EQUIVALENT); // If either node is of type ENTITY or NOTATION, compare as disconnected short thisType = thisNode->getNodeType(); short otherType = other->getNodeType(); // If either node is of type ENTITY or NOTATION, compare as disconnected if (thisType == DOMNode::ENTITY_NODE || thisType == DOMNode::NOTATION_NODE || otherType == DOMNode::ENTITY_NODE || otherType == DOMNode::NOTATION_NODE ) { return DOMNode::TREE_POSITION_DISCONNECTED; } //if this is a custom node, we don't really know what to do, just return //user should provide its own compareTreePosition logic, and shouldn't reach here if(thisType > 12) { return 0; } //if it is a custom node we must ask it for the order if(otherType > 12) { return reverseTreeOrderBitPattern(other->compareTreePosition(castToNode(this))); } // Find the ancestor of each node, and the distance each node is from // its ancestor. // During this traversal, look for ancestor/descendent relationships // between the 2 nodes in question. // We do this now, so that we get this info correct for attribute nodes // and their children. const DOMNode *node; const DOMNode *thisAncestor = castToNode(this); const DOMNode *otherAncestor = other; int thisDepth=0; int otherDepth=0; for (node = castToNode(this); node != 0; node = node->getParentNode()) { thisDepth +=1; if (node == other) // The other node is an ancestor of this one. return (DOMNode::TREE_POSITION_ANCESTOR | DOMNode::TREE_POSITION_PRECEDING); thisAncestor = node; } for (node=other; node != 0; node = node->getParentNode()) { otherDepth +=1; if (node == castToNode(this)) // The other node is a descendent of the reference node. return (DOMNode::TREE_POSITION_DESCENDANT | DOMNode::TREE_POSITION_FOLLOWING); otherAncestor = node; } const DOMNode *otherNode = other; short thisAncestorType = thisAncestor->getNodeType(); short otherAncestorType = otherAncestor->getNodeType(); // if the ancestor is an attribute, get owning element. // we are now interested in the owner to determine position. if (thisAncestorType == DOMNode::ATTRIBUTE_NODE) { thisNode = ((DOMAttrImpl *)thisAncestor)->getOwnerElement(); } if (otherAncestorType == DOMNode::ATTRIBUTE_NODE) { otherNode = ((DOMAttrImpl *)otherAncestor)->getOwnerElement(); } // Before proceeding, we should check if both ancestor nodes turned // out to be attributes for the same element if (thisAncestorType == DOMNode::ATTRIBUTE_NODE && otherAncestorType == DOMNode::ATTRIBUTE_NODE && thisNode==otherNode) return DOMNode::TREE_POSITION_EQUIVALENT; // Now, find the ancestor of the owning element, if the original // ancestor was an attribute if (thisAncestorType == DOMNode::ATTRIBUTE_NODE) { thisDepth=0; for (node=thisNode; node != 0; node = node->getParentNode()) { thisDepth +=1; if (node == otherNode) // The other node is an ancestor of the owning element return DOMNode::TREE_POSITION_PRECEDING; thisAncestor = node; } for (node=otherNode; node != 0; node = node->getParentNode()) { if (node == thisNode) // The other node is an ancestor of the owning element return DOMNode::TREE_POSITION_FOLLOWING; } } // Now, find the ancestor of the owning element, if the original // ancestor was an attribute if (otherAncestorType == DOMNode::ATTRIBUTE_NODE) { otherDepth=0; for (node=otherNode; node != 0; node = node->getParentNode()) { otherDepth +=1; if (node == thisNode) // The other node is a descendent of the reference // node's element return DOMNode::TREE_POSITION_FOLLOWING; otherAncestor = node; } for (node=thisNode; node != 0; node = node->getParentNode()) { if (node == otherNode) // The other node is an ancestor of the owning element return DOMNode::TREE_POSITION_PRECEDING; } } // thisAncestor and otherAncestor must be the same at this point, // otherwise, we are not in the same tree or document fragment if (thisAncestor != otherAncestor) return DOMNode::TREE_POSITION_DISCONNECTED; // Determine which node is of the greatest depth. if (thisDepth > otherDepth) { for (int i= 0 ; i < thisDepth - otherDepth; i++) thisNode = thisNode->getParentNode(); } else { for (int i = 0; i < otherDepth - thisDepth; i++) otherNode = otherNode->getParentNode(); } // We now have nodes at the same depth in the tree. Find a common // ancestor. DOMNode *thisNodeP, *otherNodeP; for (thisNodeP = thisNode->getParentNode(), otherNodeP = otherNode->getParentNode(); thisNodeP != otherNodeP;) { thisNode = thisNodeP; otherNode = otherNodeP; thisNodeP = thisNodeP->getParentNode(); otherNodeP = otherNodeP->getParentNode(); } // See whether thisNode or otherNode is the leftmost for (DOMNode *current = thisNodeP->getFirstChild(); current != 0; current = current->getNextSibling()) { if (current == otherNode) { return DOMNode::TREE_POSITION_PRECEDING; } else if (current == thisNode) { return DOMNode::TREE_POSITION_FOLLOWING; } } // REVISIT: shouldn't get here. Should probably throw an // exception return 0; }
void TXFMXPathFilter::walkDocument(DOMNode * n) { // Non-recursive version DOMNode * current = n; DOMNode * next; DOMNode * attParent = NULL; /* Assign NULL to remove spurious Forte warning */ bool done = false; bool treeUp = false; DOMNamedNodeMap * atts = n->getAttributes(); int attsSize = -1; int currentAtt = -1; lstsVectorType::iterator lstsIter; while (done == false && current != NULL) { if (treeUp == true) { if (current == n) { // We are complete. done = true; } else { // Remove this node from the ancestor lists for (lstsIter = m_lsts.begin(); lstsIter != m_lsts.end(); ++lstsIter) { if ((*lstsIter)->ancestorInScope == current) { (*lstsIter)->ancestorInScope = NULL; } } // Check for another sibling next = current->getNextSibling(); if (next == NULL) { current = current->getParentNode(); treeUp = true; } else { current = next; treeUp = false; } } } /* treeUp == true */ else { // Check if the current node is in the result set. The walk the children // First check if this node is in any lists, and if so, // set the appropriate ancestor nodes (if necessary) for (lstsIter = m_lsts.begin(); lstsIter != m_lsts.end(); ++lstsIter) { if ((*lstsIter)->ancestorInScope == NULL && (*lstsIter)->lst->hasNode(current)) { (*lstsIter)->ancestorInScope = current; } // } // Now that the ancestor setup is done, check to see if this node is // in scope. if (checkNodeInScope(current) && checkNodeInInput(current, (atts != NULL ? attParent : NULL))) { m_xpathFilterMap.addNode(current); } // Now find the next node! if (atts != NULL) { // Working on an attribute list currentAtt++; if (currentAtt == attsSize) { // Attribute list complete atts = NULL; current = attParent; next = current->getFirstChild(); if (next == NULL) treeUp = true; else { current = next; treeUp = false; } } else { current = atts->item(currentAtt); } } else { // Working on an element or other non-attribute node atts = current->getAttributes(); if (atts != NULL && ((attsSize = atts->getLength()) > 0)) { currentAtt = 0; attParent = current; current = atts->item(0); treeUp = false; } else { atts = NULL; next = current->getFirstChild(); if (next != NULL) { current = next; treeUp = false; } else { treeUp = true; } } } /* ! atts == NULL */ } } /* while */ }