使用Xerces C ++计算/访问DOMNode子节点的最快方法

时间:2012-07-18 13:58:27

标签: c++ xerces xerces-c

我正在尝试找出计算Xerces C ++ DOMNode对象的子元素数量的最快方法,因为我正在尝试优化使用Xerces 2.6 DOMParser的Windows应用程序的性能。似乎大部分时间都花在计算和接触孩子身上。我们的应用程序需要迭代文档中的每个节点,使用DOMNode :: setUserData()将数据附加到它,我们最初使用的是DOMNode :: getChildNodes(),DOMNodeList :: getLength()和DOMNodeList :: item(int index)计算和接触儿童,但这些是相对昂贵的操作。

当我们使用不同的呼叫习惯时,观察到了很大的性能提升 DOMNode :: getFirstChild()获取第一个子节点并调用DOMNode :: getNextSibling()来访问特定索引处的子节点或计算第一个子元素的兄弟节点数以获得总子节点数。

然而,getNextSibling()仍然是我们解析步骤的瓶颈,所以我想知道是否有更快的方法来遍历和使用Xerces访问子元素。

由于

1 个答案:

答案 0 :(得分:0)

DOMNodeList的问题在于,它实际上是一个非常简单的列表,因此lengthitem(i)之类的操作的成本为O(n),如code,例如此处的长度:

XMLSize_t DOMNodeListImpl::getLength() const{
    XMLSize_t count = 0;
    if (fNode) {
        DOMNode *node = fNode->fFirstChild;
        while(node != 0){
            ++count;
            node = castToChildImpl(node)->nextSibling;
        }
    }

    return count;
}

因此,如果您不希望在迭代时更改DOM树,则不应使用DOMNodeList,因为访问O(n)中的项会使得迭代成为O(n^2)操作-等待发生的灾难(例如,一个足够大的xml文件)。

使用[DOMNode::getFistChild()][2]DOMNode::getNextSibling()是一个足够好的迭代解决方案:

DOMNode *child = docNode->getFirstChild();
while (child != nullptr) {
    // do something with the node
    ...
    child = child->getNextSibling();
}

这在O(n^2)中按预期发生。

也可以使用[DOMNodeIterator][3],但是为了create it需要正确的DOMDocument,当需要迭代时,并不总是这样。