示例#1
0
//
//  Unlike the external getOwnerDocument, this one returns the owner document
//     for document nodes as well as all of the other node types.
//
DOMDocument *DOMNodeImpl::getOwnerDocument() const
{
    if (!this->isLeafNode())
    {
        DOMElementImpl *ep = (DOMElementImpl *)castToNode(this);
        return ep->fParent.fOwnerDocument;
    }

    //  Leaf node types - those that cannot have children, like Text.
    if (isOwned()) {

        DOMDocument* ownerDoc = fOwnerNode->getOwnerDocument();

        if (!ownerDoc) {

            assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE);
            return  (DOMDocument *)fOwnerNode;
        }
        else {
            return ownerDoc;
        }
    } else {
        assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE);
        return  (DOMDocument *)fOwnerNode;
    }
}
示例#2
0
void DOMNodeImpl::setReadOnly(bool readOnl, bool deep)
{
    this->isReadOnly(readOnl);

    if (deep) {
        for (DOMNode *mykid = castToNode(this)->getFirstChild();
            mykid != 0;
            mykid = mykid->getNextSibling()) {

            short kidNodeType = mykid->getNodeType();

            switch (kidNodeType) {
            case DOMNode::ENTITY_REFERENCE_NODE:
                break;
            case DOMNode::ELEMENT_NODE:
                ((DOMElementImpl*) mykid)->setReadOnly(readOnl, true);
                break;
            case DOMNode::DOCUMENT_TYPE_NODE:
               ((DOMDocumentTypeImpl*) mykid)->setReadOnly(readOnl, true);
               break;
            default:
                castToNodeImpl(mykid)->setReadOnly(readOnl, true);
                break;
            }
        }
    }
}
示例#3
0
const XMLCh*     DOMNodeImpl::getBaseURI() const{
    DOMNode *thisNode = castToNode(this);
    DOMNode* parent = thisNode->getParentNode();
    if (parent)
        return parent->getBaseURI();
    else
        return 0;
}
示例#4
0
// This only makes a shallow copy, cloneChildren must also be called for a
// deep clone
DOMParentNode::DOMParentNode(const DOMParentNode &other)  :
    fChildNodeList(castToNode(this))
{
    this->fOwnerDocument = other.fOwnerDocument;

    // Need to break the association w/ original kids
    this->fFirstChild = 0;
}
示例#5
0
bool DOMNodeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const{
	DOMNode *thisNode = castToNode(this);
    short type = thisNode->getNodeType();
    switch (type) {
    case DOMNode::ELEMENT_NODE: {
        const XMLCh *prefix = thisNode->getPrefix();

        // REVISIT: is it possible that prefix is empty string?
        if (prefix == 0 || !*prefix) {
            return XMLString::equals(namespaceURI, thisNode->getNamespaceURI());
        }

        if (thisNode->hasAttributes()) {
            DOMElement *elem = (DOMElement *)thisNode;
            DOMNode *attr = elem->getAttributeNodeNS(XMLUni::fgXMLNSURIName, XMLUni::fgXMLNSString);
            if (attr != 0) {
                const XMLCh *value = attr->getNodeValue();
                return XMLString::equals(namespaceURI, value);
            }
        }
        DOMNode *ancestor = getElementAncestor(thisNode);
        if (ancestor != 0) {
            return ancestor->isDefaultNamespace(namespaceURI);
        }

        return false;
    }
    case DOMNode::DOCUMENT_NODE:{
        return ((DOMDocument*)thisNode)->getDocumentElement()->isDefaultNamespace(namespaceURI);
    }

    case DOMNode::ENTITY_NODE :
    case DOMNode::NOTATION_NODE:
    case DOMNode::DOCUMENT_FRAGMENT_NODE:
    case DOMNode::DOCUMENT_TYPE_NODE:
        // type is unknown
        return false;
    case DOMNode::ATTRIBUTE_NODE:{
        if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
            return fOwnerNode->isDefaultNamespace(namespaceURI);

        }
        return false;
    }
    default:{
        DOMNode *ancestor = getElementAncestor(thisNode);
        if (ancestor != 0) {
            return ancestor->isDefaultNamespace(namespaceURI);
        }
        return false;
    }

    }
}
示例#6
0
const XMLCh* DOMNodeImpl::lookupNamespacePrefix(const XMLCh* const namespaceURI, bool useDefault, DOMElement *el) const {
    DOMNode *thisNode = castToNode(this);

    const XMLCh* ns = thisNode->getNamespaceURI();
    // REVISIT: if no prefix is available is it null or empty string, or
    //          could be both?
    const XMLCh* prefix = thisNode->getPrefix();

    if (ns != 0 && XMLString::equals(ns,namespaceURI)) {
        if (useDefault || prefix != 0) {
            const XMLCh* foundNamespace =  el->lookupNamespaceURI(prefix);
            if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) {
                return prefix;
            }
        }
    }
    if (thisNode->hasAttributes()) {
        DOMNamedNodeMap *nodeMap = thisNode->getAttributes();

        if(nodeMap != 0) {
            int length = nodeMap->getLength();

            for (int i = 0;i < length;i++) {
                DOMNode *attr = nodeMap->item(i);
                const XMLCh* attrPrefix = attr->getPrefix();
                const XMLCh* value = attr->getNodeValue();

                ns = attr->getNamespaceURI();

                if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) {
                    // DOM Level 2 nodes
                    if ((useDefault && XMLString::equals(attr->getNodeName(), XMLUni::fgXMLNSString)) ||
                        (attrPrefix != 0 && XMLString::equals(attrPrefix, XMLUni::fgXMLNSString)) &&
                        XMLString::equals(value, namespaceURI)) {
                        const XMLCh* localname= attr->getLocalName();
                        const XMLCh* foundNamespace = el->lookupNamespaceURI(localname);
                        if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) {
                            return localname;
                        }
                    }
                }
            }
        }
    }
    DOMNode *ancestor = getElementAncestor(thisNode);
    if (ancestor != 0) {
        return castToNodeImpl(ancestor)->lookupNamespacePrefix(namespaceURI, useDefault, el);
    }
    return 0;
}
示例#7
0
void DOMNodeImpl::setTextContent(const XMLCh* textContent){
    DOMNode *thisNode = castToNode(this);
    switch (thisNode->getNodeType()) 
    {
        case DOMNode::ELEMENT_NODE:
        case DOMNode::ENTITY_NODE:
        case DOMNode::ENTITY_REFERENCE_NODE:
        case DOMNode::DOCUMENT_FRAGMENT_NODE:
            {
                if (isReadOnly())
                  throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);

                // Remove all childs
                DOMNode* current = thisNode->getFirstChild();
                while (current != NULL) 
                {
                    thisNode->removeChild(current);
                    current = thisNode->getFirstChild();
                }
                if (textContent != NULL) 
                {
                    // Add textnode containing data
                    current = ((DOMDocumentImpl*)thisNode->getOwnerDocument())->createTextNode(textContent);
                    thisNode->appendChild(current);
                }
            }
            break;

        case DOMNode::ATTRIBUTE_NODE:
        case DOMNode::TEXT_NODE:
        case DOMNode::CDATA_SECTION_NODE:
        case DOMNode::COMMENT_NODE:
        case DOMNode::PROCESSING_INSTRUCTION_NODE:
            if (isReadOnly())
                throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);

            thisNode->setNodeValue(textContent);
            break;

        case DOMNode::DOCUMENT_NODE:
        case DOMNode::DOCUMENT_TYPE_NODE:
        case DOMNode::NOTATION_NODE:
            break;

        default:
            throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMNodeMemoryManager);
    }
}
示例#8
0
bool DOMNodeImpl::isEqualNode(const DOMNode* arg) const
{
    if (!arg)
        return false;

    if (isSameNode(arg)) {
        return true;
    }

    DOMNode* thisNode = castToNode(this);

    if (arg->getNodeType() != thisNode->getNodeType()) {
        return false;
    }

    // the compareString will check null string as well
    if (!XMLString::equals(thisNode->getNodeName(), arg->getNodeName())) {
        return false;
    }

    if (!XMLString::equals(thisNode->getLocalName(),arg->getLocalName())) {
        return false;
    }

    if (!XMLString::equals(thisNode->getNamespaceURI(), arg->getNamespaceURI())) {
        return false;
    }

    if (!XMLString::equals(thisNode->getPrefix(), arg->getPrefix())) {
        return false;
    }

    if (!XMLString::equals(thisNode->getNodeValue(), arg->getNodeValue())) {
        return false;
    }

    if (!XMLString::equals(thisNode->getBaseURI(), arg->getBaseURI())) {
        return false;
    }

    return true;
}
示例#9
0
const XMLCh* DOMNodeImpl::lookupNamespacePrefix(const XMLCh* namespaceURI,
                                                bool useDefault) const {
    // REVISIT: When Namespaces 1.1 comes out this may not be true
    // Prefix can't be bound to null namespace
    if (namespaceURI == 0) {
        return 0;
    }

    DOMNode *thisNode = castToNode(this);

    short type = thisNode->getNodeType();

    switch (type) {
    case DOMNode::ELEMENT_NODE: {
        return lookupNamespacePrefix(namespaceURI, useDefault, (DOMElement*)thisNode);
    }
    case DOMNode::DOCUMENT_NODE:{
        return ((DOMDocument*)thisNode)->getDocumentElement()->lookupNamespacePrefix(namespaceURI, useDefault);
    }

    case DOMNode::ENTITY_NODE :
    case DOMNode::NOTATION_NODE:
    case DOMNode::DOCUMENT_FRAGMENT_NODE:
    case DOMNode::DOCUMENT_TYPE_NODE:
        // type is unknown
        return 0;
    case DOMNode::ATTRIBUTE_NODE:{
        if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
            return fOwnerNode->lookupNamespacePrefix(namespaceURI, useDefault);
        }
        return 0;
    }
    default:{
        DOMNode *ancestor = getElementAncestor(thisNode);
        if (ancestor != 0) {
            return ancestor->lookupNamespacePrefix(namespaceURI, useDefault);
        }
        return 0;
    }
    }
}
示例#10
0
DOMNode * DOMParentNode::appendChildFast(DOMNode *newChild)
{
    // This function makes the following assumptions:
    //
    // - newChild != 0
    // - newChild is not read-only
    // - newChild is not a document fragment
    // - owner documents of this node and newChild are the same
    // - appending newChild to this node cannot result in a cycle
    // - DOMDocumentImpl::isKidOK (this, newChild) return true (that is,
    //   appending newChild to this node results in a valid structure)
    // - newChild->getParentNode() is 0
    // - there are no ranges set for this document
    //

    // Attach up
    castToNodeImpl(newChild)->fOwnerNode = castToNode(this);
    castToNodeImpl(newChild)->isOwned(true);

    // Attach before and after
    // Note: fFirstChild.previousSibling == lastChild!!
    if (fFirstChild != 0)
    {
        DOMNode *lastChild = castToChildImpl(fFirstChild)->previousSibling;
        castToChildImpl(lastChild)->nextSibling = newChild;
        castToChildImpl(newChild)->previousSibling = lastChild;
        castToChildImpl(fFirstChild)->previousSibling = newChild;
    }
    else
    {
        // this our first and only child
        fFirstChild = newChild;
        castToNodeImpl(newChild)->isFirstChild(true);
        // castToChildImpl(newChild)->previousSibling = newChild;
        DOMChildNode *newChild_ci = castToChildImpl(newChild);
        newChild_ci->previousSibling = newChild;
    }

    return newChild;
}
示例#11
0
const XMLCh*    DOMNodeImpl::getTextContent(XMLCh* pzBuffer, unsigned int& rnBufferLength) const
{

	unsigned int nRemainingBuffer = rnBufferLength;
	rnBufferLength = 0;

	if (pzBuffer)   
		*pzBuffer = 0;

	DOMNode *thisNode = castToNode(this);

	switch (thisNode->getNodeType())
	{
	case DOMNode::ELEMENT_NODE:
    case DOMNode::ENTITY_NODE:
    case DOMNode::ENTITY_REFERENCE_NODE:
    case DOMNode::DOCUMENT_FRAGMENT_NODE:
    {
		DOMNode* current = thisNode->getFirstChild();

		while (current != NULL) 
		{
			if (current->getNodeType() != DOMNode::COMMENT_NODE &&
				current->getNodeType() != DOMNode::PROCESSING_INSTRUCTION_NODE)
			{

				if (pzBuffer)
				{
					unsigned int nContentLength = nRemainingBuffer;
					castToNodeImpl(current)->getTextContent(pzBuffer + rnBufferLength, nContentLength);
					rnBufferLength += nContentLength;
					nRemainingBuffer -= nContentLength;
				}
				else 
				{
					unsigned int nContentLength = 0;
					castToNodeImpl(current)->getTextContent(NULL, nContentLength);
					rnBufferLength += nContentLength;
				}
			}

			current = current->getNextSibling();

		}
    }

    break;

    case DOMNode::ATTRIBUTE_NODE:
    case DOMNode::TEXT_NODE:
    case DOMNode::CDATA_SECTION_NODE:
    case DOMNode::COMMENT_NODE:
    case DOMNode::PROCESSING_INSTRUCTION_NODE:
    {
		const XMLCh* pzValue = thisNode->getNodeValue();
		unsigned int nStrLen = XMLString::stringLen(pzValue);

		if (pzBuffer) 
		{
			unsigned int nContentLength = (nRemainingBuffer >= nStrLen) ? nStrLen : nRemainingBuffer;
			XMLString::copyNString(pzBuffer + rnBufferLength, pzValue, nContentLength);
			rnBufferLength += nContentLength;
			nRemainingBuffer -= nContentLength;
		}
		else 
		{
			rnBufferLength += nStrLen;
		}

    }

    break;

	/***
         DOCUMENT_NODE
		 DOCUMENT_TYPE_NODE
		 NOTATION_NODE
	***/
	default:

		break;
	}

	return pzBuffer;

}
示例#12
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;

}
示例#13
0
DOMNode *XPathDocumentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
{
    // if the newChild is a documenttype node created from domimplementation, set the ownerDoc first
    if ((newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) && !newChild->getOwnerDocument())
        ((DOMDocumentTypeImpl*)newChild)->setOwnerDocument(this);

    if(newChild==NULL)
        throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, getMemoryManager());

    DOMNodeImpl *thisNodeImpl = castToNodeImpl(this);
    if (thisNodeImpl->isReadOnly())
        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, getMemoryManager());

    DOMNode* thisNode = castToNode(&fParent);
    if (newChild->getOwnerDocument() != thisNode)
        throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, getMemoryManager());

    // refChild must in fact be a child of this node (or 0)
    if (refChild!=0 && refChild->getParentNode() != thisNode)
        throw DOMException(DOMException::NOT_FOUND_ERR,0, getMemoryManager());

    // if the new node has to be placed before itself, we don't have to do anything 
    // (even worse, we would crash if we continue, as we assume they are two distinct nodes)
    if (refChild!=0 && newChild->isSameNode(refChild))
        return newChild;

    if (newChild->getNodeType() == DOMNode::DOCUMENT_FRAGMENT_NODE)
    {
        // SLOW BUT SAFE: We could insert the whole subtree without
        // juggling so many next/previous pointers. (Wipe out the
        // parent's child-list, patch the parent pointers, set the
        // ends of the list.) But we know some subclasses have special-
        // case behavior they add to insertBefore(), so we don't risk it.
        // This approch also takes fewer bytecodes.

        while(newChild->hasChildNodes())     // Move
            insertBefore(newChild->getFirstChild(),refChild);
    }

    else
    {
        DOMNode *oldparent=newChild->getParentNode();
        if(oldparent!=0)
            oldparent->removeChild(newChild);

        // Attach up
        castToNodeImpl(newChild)->fOwnerNode = thisNode;
        castToNodeImpl(newChild)->isOwned(true);

        // Attach before and after
        // Note: fFirstChild.previousSibling == lastChild!!
        if (fParent.fFirstChild == 0) {
            // this our first and only child
            fParent.fFirstChild = newChild;
            castToNodeImpl(newChild)->isFirstChild(true);
            // castToChildImpl(newChild)->previousSibling = newChild;
            DOMChildNode *newChild_ci = castToChildImpl(newChild);
            newChild_ci->previousSibling = newChild;
        } else {
            if (refChild == 0) {
                // this is an append
                DOMNode *lastChild = castToChildImpl(fParent.fFirstChild)->previousSibling;
                castToChildImpl(lastChild)->nextSibling = newChild;
                castToChildImpl(newChild)->previousSibling = lastChild;
                castToChildImpl(fParent.fFirstChild)->previousSibling = newChild;
            } else {
                // this is an insert
                if (refChild == fParent.fFirstChild) {
                    // at the head of the list
                    castToNodeImpl(fParent.fFirstChild)->isFirstChild(false);
                    castToChildImpl(newChild)->nextSibling = fParent.fFirstChild;
                    castToChildImpl(newChild)->previousSibling = castToChildImpl(fParent.fFirstChild)->previousSibling;
                    castToChildImpl(fParent.fFirstChild)->previousSibling = newChild;
                    fParent.fFirstChild = newChild;
                    castToNodeImpl(newChild)->isFirstChild(true);
                } else {
                    // somewhere in the middle
                    DOMNode *prev = castToChildImpl(refChild)->previousSibling;
                    castToChildImpl(newChild)->nextSibling = refChild;
                    castToChildImpl(prev)->nextSibling = newChild;
                    castToChildImpl(refChild)->previousSibling = newChild;
                    castToChildImpl(newChild)->previousSibling = prev;
                }
            }
        }
    }

    changed();

    Ranges* ranges = getRanges();
    if ( ranges != 0) {
        XMLSize_t sz = ranges->size();
        if (sz != 0) {
            for (XMLSize_t i =0; i<sz; i++) {
                ranges->elementAt(i)->updateRangeForInsertedNode(newChild);
            }
        }
    }

    // If insert succeeded, cache the kid appropriately
    if(newChild->getNodeType() == DOMNode::ELEMENT_NODE)
        fMyDocElement=(DOMElement *)newChild;
    else if(newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE)
        fMyDocType=(DOMDocumentType *)newChild;

    return newChild;
}
示例#14
0
const XMLCh* DOMNodeImpl::lookupNamespaceURI(const XMLCh* specifiedPrefix) const  {
    DOMNode *thisNode = castToNode(this);

    short type = thisNode->getNodeType();
    switch (type) {
    case DOMNode::ELEMENT_NODE : {
        const XMLCh* ns = thisNode->getNamespaceURI();
        const XMLCh* prefix = thisNode->getPrefix();
        if (ns != 0) {
            // REVISIT: is it possible that prefix is empty string?
            if (specifiedPrefix == 0 && prefix == specifiedPrefix) {
                // looking for default namespace
                return ns;
            } else if (prefix != 0 && XMLString::equals(prefix, specifiedPrefix)) {
                // non default namespace
                return ns;
            }
        }
        if (thisNode->hasAttributes()) {
            DOMNamedNodeMap *nodeMap = thisNode->getAttributes();
            if(nodeMap != 0) {
                int length = nodeMap->getLength();
                for (int i = 0;i < length;i++) {
                    DOMNode *attr = nodeMap->item(i);
                    const XMLCh *attrPrefix = attr->getPrefix();
                    const XMLCh *value = attr->getNodeValue();
                    ns = attr->getNamespaceURI();

                    if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) {
                        // at this point we are dealing with DOM Level 2 nodes only
                        if (specifiedPrefix == 0 &&
                            XMLString::equals(attr->getNodeName(), XMLUni::fgXMLNSString)) {
                            // default namespace
                            return value;
                        } else if (attrPrefix != 0 &&
                                   XMLString::equals(attrPrefix, XMLUni::fgXMLNSString) &&
                                   XMLString::equals(attr->getLocalName(), specifiedPrefix)) {
                            // non default namespace
                            return value;
                        }
                    }
                }
            }
        }
        DOMNode *ancestor = getElementAncestor(thisNode);
        if (ancestor != 0) {
            return ancestor->lookupNamespaceURI(specifiedPrefix);
        }
        return 0;
    }
    case DOMNode::DOCUMENT_NODE : {
        return((DOMDocument*)thisNode)->getDocumentElement()->lookupNamespaceURI(specifiedPrefix);
    }
    case DOMNode::ENTITY_NODE :
    case DOMNode::NOTATION_NODE:
    case DOMNode::DOCUMENT_FRAGMENT_NODE:
    case DOMNode::DOCUMENT_TYPE_NODE:
        // type is unknown
        return 0;
    case DOMNode::ATTRIBUTE_NODE:{
        if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
            return fOwnerNode->lookupNamespaceURI(specifiedPrefix);
        }
        return 0;
    }
    default:{
        DOMNode *ancestor = getElementAncestor(castToNode(this));
        if (ancestor != 0) {
            return ancestor->lookupNamespaceURI(specifiedPrefix);
        }
        return 0;
    }
    }
}
示例#15
0
DOMNode *DOMParentNode::insertBefore(DOMNode *newChild, DOMNode *refChild) {
    //not really in the specs, but better than nothing
    if(newChild==NULL)
        throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager);

    DOMNodeImpl *thisNodeImpl = castToNodeImpl(this);
    if (thisNodeImpl->isReadOnly())
        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMParentNodeMemoryManager);

    if (newChild->getOwnerDocument() != fOwnerDocument)
        throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMParentNodeMemoryManager);

    // Prevent cycles in the tree
    //only need to do this if the node has children
    if(newChild->hasChildNodes()) {
        bool treeSafe=true;
        for(DOMNode *a=castToNode(this)->getParentNode();
            treeSafe && a!=0;
            a=a->getParentNode())
            treeSafe=(newChild!=a);
        if(!treeSafe)
            throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager);
    }

    // refChild must in fact be a child of this node (or 0)
    if (refChild!=0 && refChild->getParentNode() != castToNode(this))
        throw DOMException(DOMException::NOT_FOUND_ERR,0, GetDOMParentNodeMemoryManager);

    // if the new node has to be placed before itself, we don't have to do anything 
    // (even worse, we would crash if we continue, as we assume they are two distinct nodes)
    if (refChild!=0 && newChild->isSameNode(refChild))
        return newChild;

    if (newChild->getNodeType() == DOMNode::DOCUMENT_FRAGMENT_NODE)
    {
        // SLOW BUT SAFE: We could insert the whole subtree without
        // juggling so many next/previous pointers. (Wipe out the
        // parent's child-list, patch the parent pointers, set the
        // ends of the list.) But we know some subclasses have special-
        // case behavior they add to insertBefore(), so we don't risk it.
        // This approch also takes fewer bytecodes.

        // NOTE: If one of the children is not a legal child of this
        // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
        // have been transferred. (Alternative behaviors would be to
        // reparent up to the first failure point or reparent all those
        // which are acceptable to the target node, neither of which is
        // as robust. PR-DOM-0818 isn't entirely clear on which it
        // recommends?????

        // No need to check kids for right-document; if they weren't,
        // they wouldn't be kids of that DocFrag.
        for(DOMNode *kid=newChild->getFirstChild(); // Prescan
              kid!=0;
              kid=kid->getNextSibling())
        {
            if (!DOMDocumentImpl::isKidOK(castToNode(this), kid))
              throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager);
        }
        while(newChild->hasChildNodes())     // Move
            insertBefore(newChild->getFirstChild(),refChild);
    }

    else if (!DOMDocumentImpl::isKidOK(castToNode(this), newChild))
        throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager);

    else
    {
        DOMNode *oldparent=newChild->getParentNode();
        if(oldparent!=0)
            oldparent->removeChild(newChild);

        // Attach up
        castToNodeImpl(newChild)->fOwnerNode = castToNode(this);
        castToNodeImpl(newChild)->isOwned(true);

        // Attach before and after
        // Note: fFirstChild.previousSibling == lastChild!!
        if (fFirstChild == 0) {
            // this our first and only child
            fFirstChild = newChild;
            castToNodeImpl(newChild)->isFirstChild(true);
            // castToChildImpl(newChild)->previousSibling = newChild;
            DOMChildNode *newChild_ci = castToChildImpl(newChild);
            newChild_ci->previousSibling = newChild;
        } else {
            if (refChild == 0) {
                // this is an append
                DOMNode *lastChild = castToChildImpl(fFirstChild)->previousSibling;
                castToChildImpl(lastChild)->nextSibling = newChild;
                castToChildImpl(newChild)->previousSibling = lastChild;
                castToChildImpl(fFirstChild)->previousSibling = newChild;
            } else {
                // this is an insert
                if (refChild == fFirstChild) {
                    // at the head of the list
                    castToNodeImpl(fFirstChild)->isFirstChild(false);
                    castToChildImpl(newChild)->nextSibling = fFirstChild;
                    castToChildImpl(newChild)->previousSibling = castToChildImpl(fFirstChild)->previousSibling;
                    castToChildImpl(fFirstChild)->previousSibling = newChild;
                    fFirstChild = newChild;
                    castToNodeImpl(newChild)->isFirstChild(true);
                } else {
                    // somewhere in the middle
                    DOMNode *prev = castToChildImpl(refChild)->previousSibling;
                    castToChildImpl(newChild)->nextSibling = refChild;
                    castToChildImpl(prev)->nextSibling = newChild;
                    castToChildImpl(refChild)->previousSibling = newChild;
                    castToChildImpl(newChild)->previousSibling = prev;
                }
            }
        }
    }

    changed();

    if (this->getOwnerDocument() != 0) {
        Ranges* ranges = ((DOMDocumentImpl *)this->getOwnerDocument())->getRanges();
        if ( ranges != 0) {
            XMLSize_t sz = ranges->size();
            if (sz != 0) {
                for (XMLSize_t i =0; i<sz; i++) {
                    ranges->elementAt(i)->updateRangeForInsertedNode(newChild);
                }
            }
        }
    }

    return newChild;
}
示例#16
0
bool DOMNodeImpl::isSameNode(const DOMNode* other) const
{
    return (castToNode(this) == other);
}
示例#17
0
short            DOMNodeImpl::compareDocumentPosition(const DOMNode* other) const {
    DOMNode* thisNode = castToNode(this);

    // If the two nodes being compared are the same node, then no flags are set on the return.
    if (thisNode == other)
        return 0;

    //if this is a custom node, we don't really know what to do, just return
    //user should provide its own compareDocumentPosition logic, and shouldn't reach here
    if(thisNode->getNodeType() > 12) {
        return 0;
    }

    //if it is a custom node we must ask it for the order
    if(other->getNodeType() > 12) {
        return reverseTreeOrderBitPattern(other->compareDocumentPosition(thisNode));
    }

    // Otherwise, the order of two nodes is determined by looking for common containers --
    // containers which contain both. A node directly contains any child nodes.
    // A node also directly contains any other nodes attached to it such as attributes
    // contained in an element or entities and notations contained in a document type.
    // Nodes contained in contained nodes are also contained, but less-directly as
    // the number of intervening containers increases.

    // If one of the nodes being compared contains the other node, then the container precedes
    // the contained node, and reversely the contained node follows the container. For example,
    // when comparing an element against its own attribute or child, the element node precedes
    // its attribute node and its child node, which both follow it.

    const DOMNode* tmpNode;
    const DOMNode* myRoot = castToNode(this);
    int myDepth=0;
    while((tmpNode=getTreeParentNode(myRoot))!=0)
    {
        myRoot=tmpNode;
        if(myRoot==other)
            return DOMNode::DOCUMENT_POSITION_CONTAINS | DOMNode::DOCUMENT_POSITION_PRECEDING;
        myDepth++;
    }

    const DOMNode* hisRoot = other;
    int hisDepth=0;
    while((tmpNode=getTreeParentNode(hisRoot))!=0)
    {
        hisRoot=tmpNode;
        if(hisRoot==thisNode)
            return DOMNode::DOCUMENT_POSITION_CONTAINED_BY | DOMNode::DOCUMENT_POSITION_FOLLOWING;
        hisDepth++;
    }

    // If there is no common container node, then the order is based upon order between the
    // root container of each node that is in no container. In this case, the result is
    // disconnected and implementation-specific. This result is stable as long as these
    // outer-most containing nodes remain in memory and are not inserted into some other
    // containing node. This would be the case when the nodes belong to different documents
    // or fragments, and cloning the document or inserting a fragment might change the order.

    if(myRoot!=hisRoot)
        return DOMNode::DOCUMENT_POSITION_DISCONNECTED | DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
              (myRoot<hisRoot?DOMNode::DOCUMENT_POSITION_PRECEDING:DOMNode::DOCUMENT_POSITION_FOLLOWING);

    // If neither of the previous cases apply, then there exists a most-direct container common
    // to both nodes being compared. In this case, the order is determined based upon the two
    // determining nodes directly contained in this most-direct common container that either
    // are or contain the corresponding nodes being compared.

    // if the two depths are different, go to the same one
    myRoot = castToNode(this);
    hisRoot = other;
    if (myDepth > hisDepth) {
        for (int i= 0 ; i < myDepth - hisDepth; i++)
            myRoot = getTreeParentNode(myRoot);
    }
    else {
        for (int i = 0; i < hisDepth - myDepth; i++)
            hisRoot = getTreeParentNode(hisRoot);
    }

    // We now have nodes at the same depth in the tree.  Find a common ancestor.
    const DOMNode *myNodeP=myRoot;
	const DOMNode *hisNodeP=hisRoot;
    while(myRoot!=hisRoot)
    {
        myNodeP = myRoot;
        hisNodeP = hisRoot;
        myRoot = getTreeParentNode(myRoot);
        hisRoot = getTreeParentNode(hisRoot);
    }

    short myNodeType=myNodeP->getNodeType();
    short hisNodeType=hisNodeP->getNodeType();
    bool bMyNodeIsChild=(myNodeType!=DOMNode::ATTRIBUTE_NODE && myNodeType!=DOMNode::ENTITY_NODE && myNodeType!=DOMNode::NOTATION_NODE);
    bool bHisNodeIsChild=(hisNodeType!=DOMNode::ATTRIBUTE_NODE && hisNodeType!=DOMNode::ENTITY_NODE && hisNodeType!=DOMNode::NOTATION_NODE);

    // If these two determining nodes are both child nodes, then the natural DOM order of these
    // determining nodes within the containing node is returned as the order of the corresponding nodes.
    // This would be the case, for example, when comparing two child elements of the same element.
    if(bMyNodeIsChild && bHisNodeIsChild)
    {
        while(myNodeP != 0)
        {
            myNodeP = myNodeP->getNextSibling();
            if(myNodeP == hisNodeP)
                return DOMNode::DOCUMENT_POSITION_FOLLOWING;
        }
        return DOMNode::DOCUMENT_POSITION_PRECEDING;
    }

    // If one of the two determining nodes is a child node and the other is not, then the corresponding
    // node of the child node follows the corresponding node of the non-child node. This would be the case,
    // for example, when comparing an attribute of an element with a child element of the same element.
    else if(!bMyNodeIsChild && bHisNodeIsChild)
        return DOMNode::DOCUMENT_POSITION_FOLLOWING;
    else if(bMyNodeIsChild && !bHisNodeIsChild)
        return DOMNode::DOCUMENT_POSITION_PRECEDING;

    else
    {
        // If neither of the two determining node is a child node and one determining node has a greater value
        // of nodeType than the other, then the corresponding node precedes the other. This would be the case,
        // for example, when comparing an entity of a document type against a notation of the same document type.
        if(myNodeType!=hisNodeType)
            return (myNodeType<hisNodeType)?DOMNode::DOCUMENT_POSITION_FOLLOWING:DOMNode::DOCUMENT_POSITION_PRECEDING;

        // If neither of the two determining node is a child node and nodeType is the same for both determining
        // nodes, then an implementation-dependent order between the determining nodes is returned. This order
        // is stable as long as no nodes of the same nodeType are inserted into or removed from the direct container.
        // This would be the case, for example, when comparing two attributes of the same element, and inserting
        // or removing additional attributes might change the order between existing attributes.
        return DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | ((myNodeP<hisNodeP)?DOMNode::DOCUMENT_POSITION_FOLLOWING:DOMNode::DOCUMENT_POSITION_PRECEDING);
    }
    // REVISIT:  shouldn't get here.   Should probably throw an
    // exception
    return 0;
}
示例#18
0
DOMNode *DOMParentNode::removeChild(DOMNode *oldChild)
{
    if (castToNodeImpl(this)->isReadOnly())
        throw DOMException(
        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMParentNodeMemoryManager);

    if (oldChild == 0 || oldChild->getParentNode() != castToNode(this))
        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMParentNodeMemoryManager);

    if (this->getOwnerDocument() !=  0  ) {
        //notify iterators
        NodeIterators* nodeIterators = ((DOMDocumentImpl *)this->getOwnerDocument())->getNodeIterators();
        if (nodeIterators != 0) {
            XMLSize_t sz = nodeIterators->size();
            if (sz != 0) {
                for (XMLSize_t i =0; i<sz; i++) {
                    if (nodeIterators->elementAt(i) != 0)
                        nodeIterators->elementAt(i)->removeNode(oldChild);
                }
            }
        }

        //fix other ranges for change before deleting the node
        Ranges* ranges = ((DOMDocumentImpl *)this->getOwnerDocument())->getRanges();
        if (ranges != 0) {
            XMLSize_t sz = ranges->size();
            if (sz != 0) {
                for (XMLSize_t i =0; i<sz; i++) {
                    if (ranges->elementAt(i) != 0)
                        ranges->elementAt(i)->updateRangeForDeletedNode(oldChild);
                }
            }
        }
    }


    // Patch linked list around oldChild
    // Note: lastChild == fFirstChild->previousSibling
    if (oldChild == fFirstChild) {
        // removing first child
        castToNodeImpl(oldChild)->isFirstChild(false);
        fFirstChild = castToChildImpl(oldChild)->nextSibling;
        if (fFirstChild != 0) {
            castToNodeImpl(fFirstChild)->isFirstChild(true);
            castToChildImpl(fFirstChild)->previousSibling = castToChildImpl(oldChild)->previousSibling;
        }
    } else {
        DOMNode *prev = castToChildImpl(oldChild)->previousSibling;
        DOMNode *next = castToChildImpl(oldChild)->nextSibling;
        castToChildImpl(prev)->nextSibling = next;
        if (next == 0) {
            // removing last child
            castToChildImpl(fFirstChild)->previousSibling = prev;
        } else {
            // removing some other child in the middle
            castToChildImpl(next)->previousSibling = prev;
        }
    }

    // Remove oldChild's references to tree
    castToNodeImpl(oldChild)->fOwnerNode = fOwnerDocument;
    castToNodeImpl(oldChild)->isOwned(false);
    castToChildImpl(oldChild)->nextSibling = 0;
    castToChildImpl(oldChild)->previousSibling = 0;

    changed();

    return oldChild;
}
示例#19
0
XERCES_CPP_NAMESPACE_BEGIN

DOMParentNode::DOMParentNode(DOMDocument *ownerDoc)
    : fOwnerDocument(ownerDoc), fFirstChild(0), fChildNodeList(castToNode(this))
{    
}