Пример #1
0
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);
  }
}
Пример #2
0
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);
}
Пример #3
0
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);
        }
      }
    }
  }
}
Пример #4
0
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);

}
Пример #5
0
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;
}
Пример #7
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;
}
Пример #8
0
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;
}
Пример #9
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 );
		}
	}
Пример #10
0
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 );
	}
Пример #11
0
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());
}
Пример #12
0
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);
	}
Пример #13
0
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);
}
Пример #14
0
// 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;
}
Пример #15
0
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);
}
Пример #16
0
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;
}
Пример #18
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);
}
Пример #19
0
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;
}
Пример #20
0
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;

}
Пример #21
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 */
}