domdeepnodelistimpl.cpp

来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 218 行

CPP
218
字号
/* * Copyright 2001-2002,2004 The Apache Software Foundation. *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *      http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: DOMDeepNodeListImpl.cpp,v 1.6 2004/09/08 13:55:51 peiyongz Exp $ */#include "DOMDeepNodeListImpl.hpp"#include "DOMElementImpl.hpp"#include "DOMDocumentImpl.hpp"#include "DOMCasts.hpp"#include "DOMNodeImpl.hpp"#include <xercesc/util/XMLUniDefs.hpp>#include <limits.h>XERCES_CPP_NAMESPACE_BEGINstatic const XMLCh kAstr[] = {chAsterisk, chNull};DOMDeepNodeListImpl::DOMDeepNodeListImpl(const DOMNode *rootNode,                                       const XMLCh *tagName)    : fRootNode(rootNode)    , fChanges(0)    , fCurrentNode(0)    , fCurrentIndexPlus1(0)    , fNamespaceURI(0)    , fMatchAllURI(false)    , fMatchURIandTagname(false){    fTagName = ((DOMDocumentImpl *)(castToNodeImpl(rootNode)->getOwnerDocument()))->getPooledString(tagName);    fMatchAll = XMLString::equals(fTagName, kAstr);}//DOM Level 2DOMDeepNodeListImpl::DOMDeepNodeListImpl(const DOMNode *rootNode,                                       const XMLCh *namespaceURI,                                       const XMLCh *localName)    : fRootNode(rootNode)    , fChanges(0)    , fCurrentNode(0)    , fCurrentIndexPlus1(0)    , fMatchAllURI(false)    , fMatchURIandTagname(true){    fTagName = ((DOMDocumentImpl *)(castToNodeImpl(rootNode)->getOwnerDocument()))->getPooledString(localName);    fMatchAll = XMLString::equals(fTagName, kAstr);    fMatchAllURI = XMLString::equals(namespaceURI, kAstr);    fNamespaceURI = ((DOMDocumentImpl *)(castToNodeImpl(rootNode)->getOwnerDocument()))->getPooledString(namespaceURI);}DOMDeepNodeListImpl::~DOMDeepNodeListImpl(){}XMLSize_t DOMDeepNodeListImpl::getLength() const{    // Reset cache to beginning of list    item(0);    // Preload all matching elements. (Stops when we run out of subtree!)    item(INT_MAX);    return fCurrentIndexPlus1;}DOMNode *DOMDeepNodeListImpl::item(XMLSize_t index) const{    return ((DOMDeepNodeListImpl*)this)->cacheItem(index);}// Start from the first child and count forward, 0-based. index>length-1// should return 0.//// Attempts to do only work actually requested, cache work already// done, and to flush that cache when the tree has changed.//// LIMITATION: ????? Unable to tell relevant tree-changes from// irrelevant ones.  Doing so in a really useful manner would seem// to involve a tree-walk in its own right, or maintaining our data// in a parallel tree.DOMNode *DOMDeepNodeListImpl::cacheItem(XMLSize_t index){    XMLSize_t currentIndexPlus1 = fCurrentIndexPlus1;    DOMNode *currentNode = fCurrentNode;    if (castToParentImpl(fRootNode)->changes() != fChanges)    {        // Tree changed. Do it all from scratch!        currentIndexPlus1 = 0;        currentNode = (DOMNode *)fRootNode;        fChanges = castToParentImpl(fRootNode)->changes();    }    else if (currentIndexPlus1 > index+1)    {        // Interested in something before cached node.  Do it all from scratch!        currentIndexPlus1 = 0;        currentNode = (DOMNode *)fRootNode;    }    else if (index+1 == currentIndexPlus1)    {        // What luck!  User is interested in cached node.        return currentNode;    }    DOMNode *nextNode = 0;// revisit - ???? How efficient is this loop? ????    // Start at the place in the tree at which we're    // currently pointing and count off nodes until we    // reach the node of interest or the end of the tree.    while (currentIndexPlus1 < index+1 && currentNode != 0)    {        nextNode = nextMatchingElementAfter(currentNode);        if (nextNode == 0)            break;        currentNode = nextNode;        currentIndexPlus1++;    }    fCurrentNode = currentNode;    fCurrentIndexPlus1 = currentIndexPlus1;    // If we found a node at the requested index, make that the current node    if (nextNode != 0)    {        return currentNode;    }    // If we didn't find a node at the requested index, return 0    return 0;}/* Iterative tree-walker. When you have a Parent link, there's often noneed to resort to recursion. NOTE THAT only Element nodes are matchedsince we're specifically supporting getElementsByTagName().*/DOMNode *DOMDeepNodeListImpl::nextMatchingElementAfter(DOMNode *current){    DOMNode *next;    while (current != 0)    {        // Look down to first child.        if (current->hasChildNodes())        {            current = current->getFirstChild();        }        // Look right to sibling (but not from root!)        else        {            if (current != fRootNode && 0 != (next = current->getNextSibling()))            {                current = next;            }            // Look up and right (but not past root!)            else            {                next = 0;                for (;                     current != fRootNode; // Stop on return to starting point                     current = current->getParentNode())                {                    next = current->getNextSibling();                    if (next != 0)                        break;                }                current = next;            }        }        // Have we found an Element with the right tagName?        // ("*" matches anything.)        if (current != 0 && current != fRootNode &&            current->getNodeType() == DOMNode::ELEMENT_NODE) {            DOMElement *currElement = (DOMElement *)current;            if (!fMatchURIandTagname) {        //DOM Level 1                if (fMatchAll ||                    XMLString::equals(currElement->getTagName(), fTagName))                    return current;            } else {        //DOM Level 2                if (!fMatchAllURI &&                    !XMLString::equals(current->getNamespaceURI(), fNamespaceURI))                    continue;                if (fMatchAll ||                    XMLString::equals(current->getLocalName(), fTagName))                    return current;            }        }        // Otherwise continue walking the tree    }    // Fell out of tree-walk; no more instances found    return 0;}XERCES_CPP_NAMESPACE_END

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?