Пример #1
0
bool RangeImpl::hasLegalRootContainer(const DOM_Node& node) const {
    if ( node==null )
        return false;

    DOM_Node rootContainer = node;
    for (; rootContainer.getParentNode()!=null; rootContainer = rootContainer.getParentNode())
        ;

    switch( rootContainer.getNodeType() ) {
    case DOM_Node::ATTRIBUTE_NODE:
    case DOM_Node::DOCUMENT_NODE:
    case DOM_Node::DOCUMENT_FRAGMENT_NODE:
        return true;
    }
    return false;
}
Пример #2
0
void RangeImpl::selectNode(const DOM_Node& refNode)
{
    validateNode(refNode);
    if ( !isLegalContainedNode(refNode)) {
        throw DOM_RangeException(
            DOM_RangeException::INVALID_NODE_TYPE_ERR, null);
    }
    //First check for the text type node
    if (refNode.getNodeType() ==  DOM_Node::TEXT_NODE)
    {
        //The node itself is the container.
        fStartContainer = refNode;
        fEndContainer   = refNode;

        //Select all the contents of the node
        fStartOffset = 0;
        fEndOffset = ((DOM_Text &)refNode).getLength();
        return;
    }

    DOM_Node parent = refNode.getParentNode();
    if (parent != null ) // REVIST: what to do if it IS null?
    {
        fStartContainer = parent;
        fEndContainer = parent;

        unsigned int i = 0;
        for (DOM_Node n = parent.getFirstChild(); n!=null, n!=refNode; n = n.getNextSibling()) {
            i++;
        }

        fStartOffset = i;
        fEndOffset = fStartOffset+1;
    }
}
Пример #3
0
DOM_Node NodeIteratorImpl::previousNode (DOM_Node node) {
	if (fDetached)
		throw DOM_DOMException(DOM_DOMException::INVALID_STATE_ERR, null);

    DOM_Node result;

    // if we're at the root, return null.
    if (node == fRoot)
			return result;

    // get sibling
    result = node.getPreviousSibling();
    if (result.isNull()) {
        //if 1st sibling, return parent
        result = node.getParentNode();
        return result;
    }

    // if sibling has children, keep getting last child of child.
    if (result.hasChildNodes()) {
        while (result.hasChildNodes()) {
            result = result.getLastChild();
        }
    }

    return result;
}
Пример #4
0
void RangeImpl::setEndAfter(const DOM_Node& refNode)
{
    if( fDetached) {
        throw DOM_DOMException(
            DOM_DOMException::INVALID_STATE_ERR, null);
    }
    if ( !hasLegalRootContainer(refNode) || !isLegalContainedNode(refNode)) {
        throw DOM_RangeException(
            DOM_RangeException::INVALID_NODE_TYPE_ERR, null);
    }

    fEndContainer = refNode.getParentNode();
    unsigned int i = 0;
    for (DOM_Node n = refNode; n!=null; n = n.getPreviousSibling(), i++) ;

    if (i ==0)
        fEndOffset = 0;
    else
        fEndOffset = i;

    if ((fDocument != refNode.getOwnerDocument() )
            && (refNode.getOwnerDocument().fImpl != 0) )
    {
        fDocument = refNode.getOwnerDocument();
        collapse(true);
    }

    //compare the start and end boundary point
    //collapse if start point is after the end point
    if(compareBoundaryPoints(DOM_Range::END_TO_START, this) == 1)
        collapse(false); //collapse the range positions to end
    else
        fCollapsed = false;
}
Пример #5
0
const DOM_Node RangeImpl::commonAncestorOf(const DOM_Node& pointA, const DOM_Node& pointB) const
{
    if (fDetached)
        throw DOM_DOMException(DOM_DOMException::INVALID_STATE_ERR, null);

    if (pointA.getOwnerDocument() != pointB.getOwnerDocument())
        throw DOM_DOMException( DOM_DOMException::WRONG_DOCUMENT_ERR, null );

    //if the containers are same then it itself is its common ancestor.
    if (pointA == pointB)
        return pointA;

    typedef RefVectorOf<NodeImpl> VectorNodes;
    VectorNodes* startV= new (((DocumentImpl*)fDocument.fImpl)->getMemoryManager()) VectorNodes(1, false, ((DocumentImpl*)fDocument.fImpl)->getMemoryManager());
    DOM_Node node;

    for (node=fStartContainer; node != null; node=node.getParentNode())
    {
        startV->addElement(node.fImpl);
    }
    VectorNodes* endV = new (((DocumentImpl*)fDocument.fImpl)->getMemoryManager()) VectorNodes(1, false, ((DocumentImpl*)fDocument.fImpl)->getMemoryManager());
    for (node=fEndContainer; node != null; node=node.getParentNode())
    {
        endV->addElement(node.fImpl);
    }

    int s = startV->size()-1;
    int e = endV->size()-1;

    NodeImpl* commonAncestor = 0;

    while (s>=0 && e>=0) {
        if (startV->elementAt(s) == endV->elementAt(e)) {
            commonAncestor = startV->elementAt(s);
        }
        else  break;
        --s;
        --e;
    }

    delete startV;
    delete endV;

    return DOM_Node(commonAncestor);
}
Пример #6
0
unsigned short RangeImpl::indexOf(const DOM_Node& child, const DOM_Node& parent) const
{
    unsigned short i = 0;
    if (child.getParentNode() != parent) return (unsigned short)-1;
    for(DOM_Node node = child.getPreviousSibling(); node!= null; node=node.getPreviousSibling()) {
        i++;
    }
    return i;
}
Пример #7
0
/** Return node, if matches or any parent if matches. */
DOM_Node NodeIteratorImpl::matchNodeOrParent (DOM_Node node) {
		DOM_Node result;

    for (DOM_Node n = fCurrentNode; n != fRoot; n = n.getParentNode()) {
        if (node == n) return n;
    }

    return result;
}
Пример #8
0
/**
 * Traverses the "right boundary" of this range and
 * operates on each "boundary node" according to the
 * how parameter.  It is a-priori assumed
 * by this method that the right boundary does
 * not contain the range's start container.
 *
 * A "right boundary" is best visualized by thinking
 * of a sample tree:
 *                 A
 *                /|\
 *               / | \
 *              /  |  \
 *             B   C   D
 *            /|\     /|\
 *           E F G   H I J
 *
 * Imagine first a range that begins between the
 * "E" and "F" nodes and ends between the
 * "I" and "J" nodes.  The start container is
 * "B" and the end container is "D".  Given this setup,
 * the following applies:
 *
 * Partially Selected Nodes: B, D<br>
 * Fully Selected Nodes: F, G, C, H, I
 *
 * The "right boundary" is the highest subtree node
 * that contains the ending container.  The root of
 * this subtree is always partially selected.
 *
 * In this example, the nodes that are traversed
 * as "right boundary" nodes are: H, I, and D.
 *
 */
DOM_Node RangeImpl::traverseRightBoundary( DOM_Node root, int how )
{
    DOM_Node next = getSelectedNode( fEndContainer, fEndOffset-1 );
    bool isFullySelected = ( next!=fEndContainer );

    if ( next==root )
        return traverseNode( next, isFullySelected, false, how );

    DOM_Node parent = next.getParentNode();
    DOM_Node clonedParent = traverseNode( parent, false, false, how );

    while( parent!=null )
    {
        while( next!=null )
        {
            DOM_Node prevSibling = next.getPreviousSibling();
            DOM_Node clonedChild =
                traverseNode( next, isFullySelected, false, how );
            if ( how!=DELETE_CONTENTS )
            {
                clonedParent.insertBefore(
                    clonedChild,
                    clonedParent.getFirstChild()
                );
            }
            isFullySelected = true;
            next = prevSibling;
        }
        if ( parent==root )
            return clonedParent;

        next = parent.getPreviousSibling();
        parent = parent.getParentNode();
        DOM_Node clonedGrandParent = traverseNode( parent, false, false, how );
        if ( how!=DELETE_CONTENTS )
            clonedGrandParent.appendChild( clonedParent );
        clonedParent = clonedGrandParent;

    }

    // should never occur
    return null;
}
Пример #9
0
bool RangeImpl::isValidAncestorType(const DOM_Node& node) const
{
    for (DOM_Node aNode = node; aNode!=null; aNode = aNode.getParentNode()) {
        short type = aNode.getNodeType();
        if ( type == DOM_Node::ENTITY_NODE
                || type == DOM_Node::NOTATION_NODE
                || type == DOM_Node::DOCUMENT_TYPE_NODE)
            return false;
    }
    return true;
}
Пример #10
0
//======================================================================
// CJM 4/17/03 ..Needed to update an attribute list... for ContentGuard
//======================================================================
bool XMLDocument::setAttributeList(char* path, DataTypeAttribute** dtAttributes)
{
	if (mDoc == NULL)
		return false;

	if (path == NULL)
		return false;

	DOM_Node child = getNode(mRootNode, path, NULL);
	char* value = getString(path);

	if (child == NULL)
		return false;

	short nType = child.getNodeType();

	DOM_Node parent = child.getParentNode();
	if (parent == NULL)
		return false;

	char* childName = child.getNodeName().transcode();
	DOM_NamedNodeMap nnodeMap = child.getAttributes();

	parent.removeChild(child);
	DOM_Element childElement = mDoc.createElement(childName);
  delete[] childName;

	int a = 0;
	DataTypeAttribute* dtAttribute;
	while ((dtAttribute = (DataTypeAttribute*)dtAttributes[a++]) != (DataTypeAttribute*)NULL)
	{

		childElement.setAttribute(dtAttribute->getName(), dtAttribute->getValue());
	}

	if (nType == DOM_Node::TEXT_NODE)
	{
		DOM_Text childText = mDoc.createTextNode((value == NULL)?"":value);
		childElement.appendChild(childText);
	}
	else
	{
		if (nType == DOM_Node::CDATA_SECTION_NODE)
		{
			DOM_CDATASection childCData = mDoc.createCDATASection((value == NULL)?"":value);
			childElement.appendChild(childCData);
		}
	}

	parent.appendChild(childElement);

	return true;

}
Пример #11
0
/**
 * Traverses the "left boundary" of this range and
 * operates on each "boundary node" according to the
 * how parameter.  It is a-priori assumed
 * by this method that the left boundary does
 * not contain the range's end container.
 *
 * A "left boundary" is best visualized by thinking
 * of a sample tree:
 *
 *                 A
 *                /|\
 *               / | \
 *              /  |  \
 *             B   C   D
 *            /|\     /|\
 *           E F G   H I J
 *
 * Imagine first a range that begins between the
 * "E" and "F" nodes and ends between the
 * "I" and "J" nodes.  The start container is
 * "B" and the end container is "D".  Given this setup,
 * the following applies:
 *
 * Partially Selected Nodes: B, D<br>
 * Fully Selected Nodes: F, G, C, H, I
 *
 * The "left boundary" is the highest subtree node
 * that contains the starting container.  The root of
 * this subtree is always partially selected.
 *
 * In this example, the nodes that are traversed
 * as "left boundary" nodes are: F, G, and B.
 *
 */
DOM_Node RangeImpl::traverseLeftBoundary( DOM_Node root, int how )
{
    DOM_Node next = getSelectedNode( getStartContainer(), getStartOffset() );
    bool isFullySelected = ( next!=getStartContainer() );

    if ( next==root )
        return traverseNode( next, isFullySelected, true, how );

    DOM_Node parent = next.getParentNode();
    DOM_Node clonedParent = traverseNode( parent, false, true, how );

    while( parent!=null )
    {
        while( next!=null )
        {
            DOM_Node nextSibling = next.getNextSibling();
            DOM_Node clonedChild =
                traverseNode( next, isFullySelected, true, how );
            if ( how!=DELETE_CONTENTS )
                clonedParent.appendChild(clonedChild);
            isFullySelected = true;
            next = nextSibling;
        }
        if ( parent==root )
            return clonedParent;

        next = parent.getNextSibling();
        parent = parent.getParentNode();
        DOM_Node clonedGrandParent = traverseNode( parent, false, true, how );
        if ( how!=DELETE_CONTENTS )
            clonedGrandParent.appendChild( clonedParent );
        clonedParent = clonedGrandParent;

    }

    // should never occur
    return null;

}
Пример #12
0
DOM_Node RangeImpl::nextNode(const DOM_Node& node, bool visitChildren) const
{

    if (node == null) return null;

    DOM_Node result;
    if (visitChildren) {
        result = node.getFirstChild();
        if (result != null) {
            return result;
        }
    }

    // if hasSibling, return sibling
    result = node.getNextSibling();
    if (result != null) {
        return result;
    }


    // return parent's 1st sibling.
    DOM_Node parent = node.getParentNode();


    while ( (parent != null) && (parent != fDocument) )
    {
        result = parent.getNextSibling();
        if (result != null) {
            return result;
        } else {
            parent = parent.getParentNode();
            if (parent == fEndContainer) return parent;

        }

    }
    // end of list, return null
    return null;
}
Пример #13
0
DOM_Node NodeIteratorImpl::nextNode (DOM_Node node, bool visitChildren) {
	if (fDetached)
		throw DOM_DOMException(DOM_DOMException::INVALID_STATE_ERR, null);

    if (node.isNull()) return fRoot;

    DOM_Node result;
    // only check children if we visit children.
    if (visitChildren) {
        //if hasChildren, return 1st child.
        if (node.hasChildNodes()) {
            result = node.getFirstChild();
            return result;
        }
    }

    // if hasSibling, return sibling
    if (node != fRoot) {
        result = node.getNextSibling();
        if (! result.isNull()) return result;


        // return parent's 1st sibling.
        DOM_Node parent = node.getParentNode();
        while (!parent.isNull() && parent != fRoot) {
            result = parent.getNextSibling();
            if (!result.isNull()) {
                return result;
            } else {
                parent = parent.getParentNode();
            }

        } // while (parent != null && parent != fRoot) {
    }
    // end of list, return null
    DOM_Node aNull;
    return aNull;
}
Пример #14
0
//======================================================================
//======================================================================
bool XMLDocument::setValue(DOM_Node currNode, char* path, DataTypeAttribute** dtAttributes, char* value)
{
	if (mDoc == NULL)
		return false;

	if (path == NULL)
		return false;

	DOM_Node child = getNode(currNode, path, dtAttributes);
	if (child == NULL)
		return false;
	DOM_Node parent = child.getParentNode();
	if (parent == NULL)
		return false;

	DOM_Node grandChild = child.getFirstChild();
	short nType = DOM_Node::TEXT_NODE;
	if (grandChild != NULL)
	{
		nType = grandChild.getNodeType();
		if (nType != DOM_Node::TEXT_NODE && nType != DOM_Node::CDATA_SECTION_NODE)
			return false;
	}

	char* childName = child.getNodeName().transcode();
	DOM_NamedNodeMap nnodeMap = child.getAttributes();

	parent.removeChild(child);
	DOM_Element childElement = mDoc.createElement(childName);
  delete[] childName;
	for (unsigned int i = 0; i < nnodeMap.getLength(); i++)
	{
		DOM_Node attNode = nnodeMap.item(i);
		childElement.setAttribute(attNode.getNodeName(), attNode.getNodeValue());
	}

	if (nType == DOM_Node::TEXT_NODE)
	{
		DOM_Text childText = mDoc.createTextNode((value == NULL)?"":value);
		childElement.appendChild(childText);
	}
	else
	{
		DOM_CDATASection childCData = mDoc.createCDATASection((value == NULL)?"":value);
		childElement.appendChild(childCData);
	}
	parent.appendChild(childElement);

	return true;
}
Пример #15
0
DOM_Node TreeWalkerImpl::getParentNode (DOM_Node node) {
	
	DOM_Node result;

    if (node.isNull() || node == fRoot) return result;

    DOM_Node newNode = node.getParentNode();
    if (newNode.isNull())  return result;

    short accept = acceptNode(newNode);

    if (accept == DOM_NodeFilter::FILTER_ACCEPT)
        return newNode;

    return getParentNode(newNode);

}
Пример #16
0
/**
 * Utility method for traversing a single node when
 * we know a-priori that the node if fully
 * selected.
 *
 */
DOM_Node RangeImpl::traverseFullySelected( DOM_Node n, int how )
{
    switch( how )
    {
    case CLONE_CONTENTS:
        return n.cloneNode( true );
    case EXTRACT_CONTENTS:
        if ( n.getNodeType()== DOM_Node::DOCUMENT_TYPE_NODE )
        {
            throw DOM_DOMException(
                DOM_DOMException::HIERARCHY_REQUEST_ERR, null);
        }
        return n;
    case DELETE_CONTENTS:
        n.getParentNode().removeChild(n);
        return null;
    }
    return null;
}
Пример #17
0
/**
 * Visits the nodes selected by this range when we know
 * a-priori that the start and end containers are not
 * the same, and we also know that neither the start
 * nor end container is an ancestor of the other.
 */
DOM_DocumentFragment RangeImpl::traverseCommonAncestors( DOM_Node startAncestor, DOM_Node endAncestor, int how )
{
    DOM_DocumentFragment frag = null;
    if ( how!=DELETE_CONTENTS)
        frag = fDocument.createDocumentFragment();

    DOM_Node n = traverseLeftBoundary( startAncestor, how );
    if ( frag!=null )
        frag.appendChild( n );

    DOM_Node commonParent = startAncestor.getParentNode();
    int startOffset = indexOf( startAncestor, commonParent );
    int endOffset = indexOf( endAncestor, commonParent );
    ++startOffset;

    int cnt = endOffset - startOffset;
    DOM_Node sibling = startAncestor.getNextSibling();

    while( cnt > 0 )
    {
        DOM_Node nextSibling = sibling.getNextSibling();
        n = traverseFullySelected( sibling, how );
        if ( frag!=null )
            frag.appendChild( n );
        sibling = nextSibling;
        --cnt;
    }

    n = traverseRightBoundary( endAncestor, how );
    if ( frag!=null )
        frag.appendChild( n );

    if ( how != CLONE_CONTENTS )
    {
        setStartAfter( startAncestor );
        collapse( true );
    }
    return frag;
}
Пример #18
0
DOM_Node TreeWalkerImpl::getNextSibling (DOM_Node node) {
	
	DOM_Node result;

    if (node.isNull() || node == fRoot) return result;

    DOM_Node newNode = node.getNextSibling();
    if (newNode.isNull()) {

        newNode = node.getParentNode();

        if (newNode.isNull() || node == fRoot)  return result;

        short parentAccept = acceptNode(newNode);

        if (parentAccept == DOM_NodeFilter::FILTER_SKIP) {
            return getNextSibling(newNode);
        }

        return result;
    }

    short accept = acceptNode(newNode);

    if (accept == DOM_NodeFilter::FILTER_ACCEPT)
        return newNode;
    else
    if (accept == DOM_NodeFilter::FILTER_SKIP) {
        DOM_Node fChild =  getFirstChild(newNode);
        if (fChild.isNull()) {
            return getNextSibling(newNode);
        }
        return fChild;
    }
    return getNextSibling(newNode);

}
Пример #19
0
void RangeImpl::insertNode(DOM_Node& newNode)
{
    if (newNode == null) return; //don't have to do anything

    for (DOM_Node aNode = fStartContainer; aNode!=null; aNode = aNode.getParentNode()) {
        if (aNode.fImpl->isReadOnly()) {
            throw DOM_DOMException(
                DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null);
        }
    }

    if (fDocument != newNode.getOwnerDocument()) {
        throw DOM_DOMException(
            DOM_DOMException::WRONG_DOCUMENT_ERR, null);
    }

    // Prevent cycles in the tree.
    //isKidOK() is not checked here as its taken care by insertBefore() function
    if (isAncestorOf( newNode, fStartContainer)) {
        throw DOM_DOMException(
            DOM_DOMException::HIERARCHY_REQUEST_ERR, null);
    }

    if( fDetached) {
        throw DOM_DOMException(
            DOM_DOMException::INVALID_STATE_ERR, null);
    }

    int type = newNode.getNodeType();
    if (type == DOM_Node::ATTRIBUTE_NODE
            || type == DOM_Node::ENTITY_NODE
            || type == DOM_Node::NOTATION_NODE
            || type == DOM_Node::DOCUMENT_NODE)
    {
        throw DOM_RangeException(
            DOM_RangeException::INVALID_NODE_TYPE_ERR, null);
    }


    DOM_Node parent;
    DOM_Node next;

    if (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) {

        //set 'parent' and 'next' here
        parent = fStartContainer.getParentNode();

        //split the text nodes
        if (fStartOffset > 0)
            ((DOM_Text &)fStartContainer).splitText(fStartOffset);

        //update the new start information later. After inserting the first newNode
        if (fStartOffset == 0)
            next = fStartContainer;
        else
            next = fStartContainer.getNextSibling();

    } // end of text handling
    else {
        parent = fStartContainer;

        next = fStartContainer.getFirstChild();
        for(unsigned int i = 0; (i < fStartOffset) && (next != null); i++) {
            next=next.getNextSibling();
        }
    }

    if (parent != null) {
        if (next != null)
            parent.insertBefore(newNode, next);
        else
            parent.appendChild(newNode);
    }
}