Xerces-C++ DOM編程指南(一)__Linux

來源:互聯網
上載者:User

 原文地址:http://xerces.apache.org/xerces-c/program-dom.html


設計目標
    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()方法用來釋放所有的通過creatxxxFactory 方法建立的“孤兒(即現在已不再使用的)”資源,對象銷毀而釋放的記憶體資源由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.有些疑問,疑譯文是我自己的理解)。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.