科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航



ZDNet>软件频道>中间件-zhiding>DOM编程指南(一)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

Xerces-C++2.8.0包含了W3C DOM(文档对象模型)Level 3的部分实现

来源:CSDN 2007年09月28日

关键字:编程 DOM ghost

设计目标
    DOM的C++实现是基于阿帕奇推荐的DOM(Apache Recommended DOM C++ binding).
设计目标是为了满足如下需求:
1.降低内存占用率.
2.提高应用程序的性能,特别是那些服务器类型和多线程的应用程序.
3.多处理系统中优异的延展性.
4.比起Java来其风格更像C++

Xerces-C++对DOM Level 3的支持
Xerces-C++2.8.0包含了W3C DOM(文档对象模型)Level 3的部分实现,此实现是实验性的.详情请查看文档DOM Level 3 Support

使用DOM API
    在您的程序代码中访问API
#include <xercesc/dom/DOM.hpp>
在头文件<dom/DOM.hpp>中,包含了DOM API类所需要的全部头文件

类名
     DOM类名都以“DOM”为前缀(如果类名本身不以“DOM”开头),例如“DOMNode”,这样是为了防止DOM类名与这样一些类名混淆:一些名称可能已经在应用程序或基于DOM的应用程序所必须链接的类中所使用了。
   DOMDocument*   myDocument;
   DOMNode*       aNode;
   DOMText*       someText;

对象管理
     应用程序在C++ DOM中将使用标准C++指针直接访问对象所实现的节点。
思考下面的代码段:
   DOMNode*       aNode;
   DOMNode* docRootNode;
   aNode = someDocument->createElement(anElementName);
   docRootNode = someDocument->getDocumentElement();
   docRootNode->appendChild(aNode);

内存管理
    C++ DOM的实现提供了一个release()方法用来释放所有的通过creatxxx工厂方法创建的“孤儿(即现在已不再使用的)”资源,对象销毁而释放的内存资源由C++ DOM的实现进行管理。更详细说明请查看Apache Recommended DOM C++ binding。

使用DOMImplementation::createXXX创建对象
    用户必须调用release() 函数来释放由DOMImplementation::createXXX创建的现在已经使用完毕的对象,如DOMBuilder, DOMWriter, DOMDocument, DOMDocumentType。
试图访问已经被释放的对象将导致异常行为。
1.当一个DOMDocument对象被释放后,所有与此对象相关的子对象以及其所拥有的对象(如DOMRange, DOMTreeWalker, DOMNodeIterator或任何孤立的节点)也将被释放。
2.当复制一个DOMDocument对象时,这个复制文档对象不再与其父类文档对(original master document)象有任何联系,并且要显示的释放。
3.当一个DOMDocumentType被插入一个DOMDocument后,这个DOMDocumentType也因此有了一个宿主(owner),当它的宿主(owner document)被释放后它也会被自动释放,此时如果释放这个节点时会产生一个DOMException::INVALID_ACCESS_ERR 异常。

使用DOMDocument::createXXX创建对象
    用户应该调用release()函数去显示释放任何一个孤立的节点。当一个孤立节点被释放后,与其相关联的子节点也将被释放。访问一个被释放的节点将导致异常行为。那些孤立的节点最终将会释放,如果现在还没有释放,那么在他们的宿主(owner document)被释放时他们就会被释放。
试图释放一个有父亲的节点将会导致一个DOMException::INVALID_ACCESS_ERR异常。

使用DOMDocumentRange::createRange或者DOMDocumentTraversal::createXXX创建对象
     当DOMRange, DOMNodeIterator, DOMTreeWalker使用完毕后,用户应该调用release()函数。访问一个被释放的对象将导致异常行为。那些对象最终将会释放,如果现在还没有释放,那么在他们的宿主(owner document)被释放时他们就会被释放。
如下有一个例子:
    //
    //  Create a small document tree
    //
    {
        XMLCh tempStr[100];

        XMLString::transcode("Range", tempStr, 99);
        DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(tempStr, 0);
       
        XMLString::transcode("root", tempStr, 99);
        DOMDocument*   doc = impl->createDocument(0, tempStr, 0);
        DOMElement*   root = doc->getDocumentElement();

        XMLString::transcode("FirstElement", tempStr, 99);
        DOMElement*   e1 = doc->createElement(tempStr);
        root->appendChild(e1);

        XMLString::transcode("SecondElement", tempStr, 99);
        DOMElement*   e2 = doc->createElement(tempStr);
        root->appendChild(e2);

        XMLString::transcode("aTextNode", tempStr, 99);
        DOMText*       textNode = doc->createTextNode(tempStr);
        e1->appendChild(textNode);

        //optionally, call release() to release the resource associated with the range after done
        DOMRange* range = doc->createRange();
        range->release();

        //removedElement is an orphaned node, optionally call release() to release associated resource
        DOMElement* removedElement = root->removeChild(e2);
        removedElement->release();

        // no need to release this returned object which is owned by implementation
        XMLString::transcode("*", tempStr, 99);
        DOMNodeList*    nodeList = doc->getElementsByTagName(tempStr);

        // done with the document, must call release() to release the entire document resources
        doc->release();
    };

字符串型别
    C++ DOM使用普通的的无结尾标志的(XMLCh *)UTF-16字符串作为字符串型别,这些(XMLCh*) utf-16 型别的字符串开销极低。
   //C++ DOM
   const XMLCh* nodeValue = aNode->getNodeValue();
所有的字符串数据都将会保存在内存中直到文档对象被销毁。但是像这些字符串数据在执行过程中必要时有可能会被循环利用(RECYCLED),用户应该使用合适的返回字符串副本作为类型安全的引用.
例如当一个DOMNode被释放后,为其分配的内存资源将会被循环在利用。

   XMLCh xfoo[] = {chLatin_f, chLatin_o, chLatin_o, chNull};

   // pAttr has node value = "foo"
   // fNodeValue has "foo"
   pAttr->setNodeValue(xfoo);
   const XMLCh* fNodeValue = pAttr->getNodeValue();

   // fNodeValue has "foo"
   // make a copy of the string for future reference
   XMLCh* oldNodeValue = XMLString::replicate(fNodeValue);

   // release the node pAttr
   pAttr->release()

   // other operations

   // implementation may have recycled the memory of the pAttr already
   // so it's not safe to expect fNodeValue still have "foo"
   if (XMLString::compareString(xfoo, fNodeValue))
       printf("fNodeValue has some other content\n");

   // should use your own safe copy
   if (!XMLString::compareString(xfoo, oldNodeValue))
       printf("Use your own copy of the oldNodeValue if want to reference the string later\n");

   // delete your own replicated string when done
   XMLString::release(&oldNodeValue);

    如果调用DOMNode::setNodeValue() 去设置一个新节点值,执行时仅仅是简单的重写节点值所占用的内存区域,因此先前的指针现在就会自动的指向新的值。用户应该使用合适的先前所返回的字符串副本作为类型安全的引用.例如:
    XMLCh xfoo[] = {chLatin_f, chLatin_o, chLatin_o, chNull};
   XMLCh xfee[] = {chLatin_f, chLatin_e, chLatin_e, chNull};

   // pAttr has node value = "foo"
   pAttr->setNodeValue(xfoo);
   const XMLCh* fNodeValue = pAttr->getNodeValue();

   // fNodeValue has "foo"
   // make a copy of the string for future reference
   XMLCh* oldNodeValue = XMLString::replicate(fNodeValue);

   // now set pAttr with a new node value "fee"
   pAttr->setNodeValue(xfee);

   // should not rely on fNodeValue for the old node value, it may not compare
   if (XMLString::compareString(xfoo, fNodeValue))
       printf("Should not rely on fNodeValue for the old node value\n");

   // should use your own safe copy
   if (!XMLString::compareString(xfoo, oldNodeValue))
       printf("Use your own copy of the oldNodeValue if want to reference the string later\n");

   // delete your own replicated string when done
   XMLString::release(&oldNodeValue);

     这样做是当我们成百上千次调用DOMNode::setNodeValue()时防止内存消耗成等比级数的增长。这一设计容许用户主动的选择返回的字符串应该手动的让它留在内存中还是将这个字符串拷贝到应用程序自己的堆栈中。(这句原文是This design allows users to actively select which returned string should stay in memory by manually copying the string to application's own heap.有些疑问,疑译文是我自己的理解)。



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1805106

推广二维码
邮件订阅

如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

重磅专题