本文翻译自Xerces开发文档,为了能更好理解自行翻译学习,没有完全一一对应。英语不是很好,还望理解。
<dom/DOM.hpp> 包含了所有DOM API头文件,所以程序需要#include <xercesc/dom/DOM.hpp>
为了防止与程序中其他名称出现冲突,所以DOM类名都以“DOM”作为前缀。如
DOMDocument* myDocument;
DOMNode* aNode;
DOMText* someText;
程序将使用常规的C++指针访问DOM节点。
DOMNode* aNode;
DOMNode* docRootNode;
aNode = someDocument->createElement(anElementName);
docRootNode = someDocument->getDocumentElement();
docRootNode->appendChild(aNode);
C++ DOM 提供Release()方法来释放任何由createXXXX工厂方法创建,但已经被“遗弃”的资源。
用户必须调用release()来释放 任何由DOMImplementation::createXXXX创建的对象。如DOMLSParser,DOMLSSerializer, DOMLSInput, DOMLSOutput, DOMDocument, DOMDocumentType)
访问已经被释放的对象将会引发异常。此外还需要注意以下几点:
1、 当一个DOMDocument 被释放,它的所有子节点和与它相关的子对象(e.g.DOMRange, DOMTreeWalker, DOMNodeIterator or any orphaned nodes)都会被释放。
2、 当一个DOMDocument 被克隆时,克隆出来的document 和原先的document 已经没有关系了,需要显示释放。
3、 当一个DOMDocumentType 被插入到一个DOMDocument 中,因此有了owner,当owner被释放时它也自动被释放。如果自行释放将引发DOMException::INVALID_ACCESS_ERR异常。
用户可以调用release()来释放任何被“遗弃”的节点。当一个节点被释放,它相关的子对象也会被释放。访问一个已经被释放的节点将引发异常。所有的节点最终都将被释放,如果没有被释放,当它的父节点被释放时它也将被释放。
注意:自行释放一个带有父节点的节点将引发DOMException::INVALID_ACCESS_ERR 异常
用当已经用完了 DOMRange,DOMNodeIterator, DOMTreeWalker.时,需要调用release() 来释放这些对象。
C++ DOM使用了以空字符结尾的utf-16字符串 (XMLCh *)做为其字符串类型。该字符串来下 (XMLCh *)开销比较小。
所有的字符串数据都将存在于内存中直到document 对象被释放。但是在必要的时候这些字符串数据会被实现重用。用户需要适当的保存返回字符串的副本。
例如,当一个DOMNode被释放之后,为该节点值分配的空间可能会被重用。
DOMDocument* Createdocument()
{
XMLCh tempStr[100];
XMLString::transcode("range", tempStr, 99);
DOMImplementation* impl =DOMImplementationRegistry::getDOMImplementation(tempStr);
XMLString::transcode("root", tempStr, 99);
DOMDocument* doc = impl->createDocument(0, tempStr,0);
DOMElement* root = doc->getDocumentElement();
returndoc;
}
void reuseNodeMemory()
{
DOMDocument* pdoc = Createdocument();
XMLCh xfoo[] = {chLatin_f, chLatin_o,chLatin_o, chNull};
DOMText *pAttr =pdoc->createTextNode(xfoo);
// pAttr hasnode value = "foo"
// fNodeValuehas "foo"
pAttr->setNodeValue(xfoo);
constXMLCh* fNodeValue = pAttr->getNodeValue();
// fNodeValuehas "foo"
// make a copyof the string for future reference
XMLCh* oldNodeValue = XMLString::replicate(fNodeValue);
// release thenode pAttr
pAttr->release();
XMLCh tempStr[100];
XMLString::transcode("new string", tempStr, 99);
DOMText *pNewText =pdoc->createTextNode(xfoo);
pNewText->setNodeValue(tempStr);
DOMText *pNewText2 =pdoc->createTextNode(xfoo);
//implementation may have recycled the memory of the pAttr already
// so it's notsafe to expect fNodeValue still have "foo"
char *pch= XMLString::transcode(fNodeValue);
if(XMLString::compareString(xfoo, fNodeValue))
printf("fNodeValuehas some other content :êo%s\n",pch);
// should useyour own safe copy
if(!XMLString::compareString(xfoo, oldNodeValue))
printf("Useyour own copy of the oldNodeValue if want to reference the string later\n");
// delete yourown replicated string when done
XMLString::release(&oldNodeValue);
}
当调用DOMNode::setNodeValue()设置新值时,实现仅仅是简单的改写了节点的内存,所以之前的指针也将被改写为新的值。这防止DOMNode::setNodeValue()被调用几百次而导致增加内存消耗。
voidoverwriteNodeMemory()
{
DOMDocument* pdoc = Createdocument();
XMLCh xfoo[] = {chLatin_f, chLatin_o, chLatin_o,chNull};
XMLCh xfee[] = {chLatin_f, chLatin_e,chLatin_e, chNull};
// pAttr hasnode value = "foo"
DOMText *pAttr =pdoc->createTextNode(xfoo);
pAttr->setNodeValue(xfoo);
constXMLCh* fNodeValue = pAttr->getNodeValue();
// fNodeValuehas "foo"
// make a copyof the string for future reference
XMLCh* oldNodeValue =XMLString::replicate(fNodeValue);
// now setpAttr with a new node value "fee"
pAttr->setNodeValue(xfee);
// should notrely on fNodeValue for the old node value, it may not compare
char *pch= XMLString::transcode(fNodeValue);
if(XMLString::compareString(xfoo, fNodeValue))
{
printf("fNodeValuehas some other content :êo%s\n",pch);
}
// should useyour own safe copy
if(!XMLString::compareString(xfoo, oldNodeValue))
printf("Useyour own copy of the oldNodeValue if want to reference the string later\n");
// delete yourown replicated string when done
XMLString::release(&oldNodeValue);
}
fNodeValue的值也被改变了。