这两天一直想学习在C++中环境下进行XML编程,但是进度有点缓慢,目前只学会用DOM进行一些处理,有些处理还有问题(如newDoc方法中不知如何在b.xml文件头加入xml version="1.0"等等内容),我随便写了个XML文件进行测试:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE person SYSTEM "a.dtd">
<person>
<people>
<name>陈</name>
<sex>male</sex>
<age>30</age>
</people>
<people>
<name>abched</name>
<sex>female</sex>
<age>1</age>
</people>
</person>
声明了一个XML处理类:
struct suPerson
{
string _name;
string _sex;
int _age;
};
class TParse
{
private:
string _strErrMsg;
DOMImplementation *_impl;
DOMBuilder *_parser;
DOMWriter* _writer;
DOMDocument* _doc;
DOMDocument* _newDoc;
vector<suPerson> _vecPerson;
bool parseNode(DOMNode *n);
public:
TParse();
~TParse();
bool parse(const char* strXmlFile);
bool newDoc(const char* strXmlFile);
string getErrMsg()
{
return _strErrMsg;
}
vector<suPerson> getVector()
{
return _vecPerson;
}
};
类的具体定义如下:
#include "Parse.h"
TParse::TParse()
{
try
{
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch)
{
char* message = XMLString::transcode(toCatch.getMessage());
_strErrMsg = message;
XMLString::release(&message);
throw _strErrMsg;
}
XMLCh tempStr[100];
XMLString::transcode("LS", tempStr, 99);
_impl = DOMImplementationRegistry::getDOMImplementation(tempStr);
_parser = _impl->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
_writer = ((DOMImplementationLS*)_impl)->createDOMWriter();
// optionally, set some DOMWriter features
// set the format-pretty-print feature
if (_writer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true))
_writer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
// set the byte-order-mark feature
if (_writer->canSetFeature(XMLUni::fgDOMWRTBOM, true))
_writer->setFeature(XMLUni::fgDOMWRTBOM, true);
}
TParse::~TParse()
{
_parser->release();
if (_newDoc)
_newDoc->release();
_writer->release();
}
bool TParse::parse(const char* strXmlFile)
{
try
{
_doc = _parser->parseURI(XMLString::transcode(strXmlFile));
}
catch (const XMLException& toCatch)
{
char* message = XMLString::transcode(toCatch.getMessage());
_strErrMsg = message;
XMLString::release(&message);
throw _strErrMsg;
}
catch (const DOMException& toCatch)
{
char* message = XMLString::transcode(toCatch.msg);
_strErrMsg = message;
XMLString::release(&message);
throw _strErrMsg;
}
catch (...)
{
_strErrMsg = "Unexpected Exception \n";
throw _strErrMsg;
}
if (!_doc)
{
_strErrMsg = "_doc is null";
return false;
}
DOMNode* n = (DOMNode*)_doc->getDocumentElement();
_vecPerson.clear();
if (!n)
{
_strErrMsg = "it is not an legal node";
return false;
}
if (n)
{
if (n->getNodeType() == DOMNode::ELEMENT_NODE)
{
DOMNodeList* nodeList = n->getChildNodes();
unsigned int nListLen = nodeList->getLength();
for (unsigned int i=0; i<nListLen; ++i)
{
DOMNode* nodeTemp = nodeList->item(i);
if (nodeTemp->getNodeType() == DOMNode::ELEMENT_NODE)
{
suPerson suTemp;
memset(&suTemp, 0, sizeof(suTemp));
for (DOMNode* node1=nodeTemp->getFirstChild(); node1!=0; node1=node1->getNextSibling())
{
char* name = XMLString::transcode(node1->getNodeName());
string strTemp = name;
if (strTemp == "name")
{
suTemp._name = XMLString::transcode(node1->getFirstChild()->getNodeValue());
node1->getFirstChild()->setNodeValue(XMLString::transcode((suTemp._name+" hello").c_str()));
}
else if (strTemp == "sex")
{
suTemp._sex = XMLString::transcode(node1->getFirstChild()->getNodeValue());
}
else if (strTemp == "age")
{
suTemp._age = XMLString::parseInt(node1->getFirstChild()->getNodeValue());
}
XMLString::release(&name);
}
_vecPerson.push_back(suTemp);
}
}
}
}
return true;
}
//---------------------------------------------------------------------------
bool TParse::newDoc(const char* strXmlFile)
{
try
{
_newDoc = _impl->createDocument();
}
catch (const XMLException& toCatch)
{
char* message = XMLString::transcode(toCatch.getMessage());
_strErrMsg = message;
XMLString::release(&message);
throw _strErrMsg;
}
catch (const DOMException& toCatch)
{
char* message = XMLString::transcode(toCatch.msg);
_strErrMsg = message;
XMLString::release(&message);
throw _strErrMsg;
}
catch (...)
{
_strErrMsg = "Unexpected Exception \n";
throw _strErrMsg;
}
DOMElement* root = _newDoc->createElement(XMLString::transcode("person"));
for (unsigned int i=0; i<2; ++i)
{
DOMElement* item = _newDoc->createElement(XMLString::transcode("people"));
DOMElement* name = _newDoc->createElement(XMLString::transcode("name"));
DOMAttr* attr = _newDoc->createAttribute(XMLString::transcode("id"));
attr->setNodeValue(XMLString::transcode("hello"));
name->appendChild(_newDoc->createTextNode(XMLString::transcode("C陈")));
name->setAttributeNode(attr);
DOMElement* sex = _newDoc->createElement(XMLString::transcode("male"));
sex->appendChild(_newDoc->createTextNode(XMLString::transcode("male")));
DOMElement* age = _newDoc->createElement(XMLString::transcode("age"));
age->appendChild(_newDoc->createTextNode(XMLString::transcode("30")));
item->appendChild(name);
item->appendChild(sex);
item->appendChild(age);
root->appendChild(item);
}
_newDoc->appendChild(root);
// construct the LocalFileFormatTarget
XMLFormatTarget *myFormatTarget = new LocalFileFormatTarget(strXmlFile);
// serialize a DOMNode to the local file "myXMLFile.xml"
_writer->writeNode(myFormatTarget, *_newDoc->getDocumentElement());
// optionally, you can flush the buffer to ensure all contents are written
myFormatTarget->flush();
// release the memory
delete myFormatTarget;
return true;
}
测试代码:
#include "Parse.h"
int main (int argc, char* args[])
{
try
{
TParse parse;
if (!parse.parse("a.xml"))
{
cout << "error: " << parse.getErrMsg() << endl;
}
vector<suPerson> vecTemp = parse.getVector();
for (unsigned int i=0; i<vecTemp.size(); ++i)
{
cout << i << "--------------" << endl;
cout << "name: " << vecTemp[i]._name << endl;
cout << "sex: " << vecTemp[i]._sex << endl;
cout << "age: " << vecTemp[i]._age << endl;
}
cout << "--------------------------------" << endl;
parse.newDoc("b.xml");
}
catch(const string& str)
{
cout << "error: " << str << endl;
}
cin.get();
return 0;
}
这边请教大家一个问题,如何用代码实现在生成的b.xml头部加上XML的版本和编码声明?通过ultraedit看b.xml,里面的字符的默认格式是UNICODE编码