作者:Kagula
日期:2009/10/14
有在VS2008中,使用C++语言开发的初步经验。
利用示例,表述Xercesc3.07软件开发包DOM API的使用
Xercesc DOM
[1]VisualStudio2008 with SP1 C++
[2]Xercesc3.01
假设Xercesc安装在D:/SDK/xerces-c-3.0.1-x86-windows-vc-9.0位置
在VS2008中设置D:/SDK/xerces-c-3.0.1-x86-windows-vc-9.0/include为头文件路径
在VS2008中设置D:/SDK/xerces-c-3.0.1-x86-windows-vc-9.0/lib为库文件路径
复制D:/SDK/xerces-c-3.0.1-x86-windows-vc-9.0/bin位置下的xerces-c_3_0.dll文件和xerces-c_3_0D.dll文件到你项目目录中。
下面的代码为:Xercesc初始化和Terminate的例子
#ifndef _DEBUG
#pragma comment( lib, "xerces-c_3.lib" )
#else
#pragma comment( lib, "xerces-c_3D.lib" )
#endif
#include <xercesc/util/PlatformUtils.hpp>
// Other include files, declarations, and non-Xerces-C++ initializations.
using namespace xercesc;
int main(int argc, char* argv[])
{
try {
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch) {
// Do your failure processing here
return 1;
}
// Do your actual work with Xerces-C++ here.
XMLPlatformUtils::Terminate();
// Other terminations and cleanup.
return 0;
}
本节包含内容:XML文件格式、判断节点类型、取节点名称、取节点值。
XML文件的典型格式,如下
<节点名称1>
<节点名称1-1 属性名1=属性值1 属性名2=属性值2>
<节点名称1-1-1> <!- 节点名为 节点名称1-1-1节点值无 -->
Context <!- 节点名为#text 节点值为Context -->
<!- 若Context为空,则没有#text节点 -->
</节点名称1-1-1>
</节点名称1-1>
<节点名称 1-2>
</节点名称1-2>
</节点名称1>
参考Domcount例程,得到DOMNode对象
首先判断DOMNode对象的节点类型、然后,对节点内容和值分别存储。
if (static_cast<DOMNode *>(n)->getNodeType() == DOMNode::ELEMENT_NODE)
{
//取节点名称。这里取节点值是没有意义的
char *name = XMLString::transcode(static_cast<DOMNode *>(n)->getNodeName());
pThis->m_strName = name; //存放节点名称
XMLString::release(&name);
//如果本节点有属性,存储属性信息到pThis对象.begin
if(static_cast<DOMNode *>(n)->hasAttributes()) {
// get all the attributes of the node
DOMNamedNodeMap *pAttributes = static_cast<DOMNode *>(n)->getAttributes();
const XMLSize_t nSize = pAttributes->getLength();
std::string strKey,strValue; //用来存放属性名和属性值
for(XMLSize_t i=0;i<nSize;++i) {
DOMAttr *pAttributeNode = (DOMAttr*) pAttributes->item(i);
// get attribute name
char *name = XMLString::transcode(pAttributeNode->getName());
// get attribute type
char *value = XMLString::transcode(pAttributeNode->getValue());
//存放属性名和属性值
strKey = name,strValue=value,pThis->m_mapAttr[strKey]=strValue;
XMLString::release(&name);
XMLString::release(&value);
}
//如果本节点有属性,存储属性信息到pThis对象.end
}
Else if (static_cast<DOMNode *>(n)->getNodeType() == DOMNode::TEXT_NODE)
{
//节点名为#text的节点,可以取其节点值
//… omit some code …
char *value = XMLString::transcode(static_cast<DOMNode *>(n)->getNodeValue());
//… omit some code …
}
备注:Xercesc直接支持UTF-8编码的中文。
这里通过一个完整的例子来举例
#include <iostream>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#pragma comment(lib,"xerces-c_3")
XERCES_CPP_NAMESPACE_USE
using namespace std;
// StrXML class copied from Xerces-2.8 distro.
class StrXML
{
public :
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
StrXML(const char* const toTranscode)
{
// Call the private transcoding method
fLocalForm = XMLString::transcode(toTranscode);
}
~StrXML()
{
XMLString::release(&fLocalForm);
}
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
const XMLCh* utf16() const
{
return fLocalForm;
}
private :
// -----------------------------------------------------------------------
// Private data members
//
// fLocalForm
// This is the local code page form of the string.
// -----------------------------------------------------------------------
XMLCh* fLocalForm;
};
int main (int , char **) {
XMLPlatformUtils::Initialize();
DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(StrXML("").utf16());
if (impl == NULL)
throw string("Implementation is NULL in create document.");
// Create the document with one tag
DOMDocument *doc = impl->createDocument(0, StrXML("session").utf16(),
impl->createDocumentType(StrXML("dummy").utf16(),
0, 0));
DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer();
DOMLSOutput *theOutput = ((DOMImplementationLS*)impl)->createLSOutput();
DOMConfiguration *configuration = theSerializer->getDomConfig();
//a small document tree .begin
DOMElement* root = doc->getDocumentElement();
DOMElement* e1 = doc->createElement(StrXML("FirstElement").utf16());
e1->setAttribute(StrXML("attributeName").utf16(),StrXML("attributeValue").utf16());
root->appendChild(e1);
DOMText* textNode = doc->createTextNode(StrXML("aTextNode").utf16());
e1->appendChild(textNode);
//a small document tree .end
// Have a nice output
if (configuration->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true))
configuration->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
// Add the declaration?
if (configuration->canSetParameter(XMLUni::fgDOMXMLDeclaration, true))
configuration->setParameter(XMLUni::fgDOMXMLDeclaration, true);
LocalFileFormatTarget *myFormTarget = new LocalFileFormatTarget(StrXML("outfile.xml").utf16());
theOutput->setByteStream(myFormTarget);
if (doc->getDoctype() == NULL) {
cerr << "The doc type is null./n";
exit(-1);
}
theSerializer->write(doc, theOutput);
DOMRange *range = doc->createRange();
range->release();
theOutput->release();
theSerializer->release();
XMLPlatformUtils::Terminate();
}
例子中的range用来释放e1、textNode对象的存储空间。
生成a simple document tree部份的代码可以参考
http://xerces.apache.org/xerces-c/program-dom-3.html
文档《Create a small document tree》部份
经过测试,使用Opera和IE浏览器打开xml文件,中文可以正常显示,但是使用EditPlus3打开文件,显示乱码,不过这不是本文讨论的重点。
[1]Xercesc官网
http://xerces.apache.org/xerces-c/program-dom-3.html
[2] 基于XERCES-C编程中的中文(encoding)设置问题的解决方法
http://www.cnitblog.com/silenceburn/archive/2006/04/02/8506.html
内容:采用GB2312编码处理中文,生成XML文档