- //XercesParserXml.h
- #ifndef XERCES_PARSER_XML_H__
- #define XERCES_PARSER_XML_H__
- #include <string>
- class XercesParserXml {
- public:
- bool has(const std::string& srcByte, const std::string& node) const;
- std::string get(const std::string& srcByte, const std::string& node) const;
- bool set(std::string& srcByte, const std::string& node, const std::string& value);
- bool del(std::string& srcByte, const std::string& node);
- private:
- };
- #endif
- //XercesParserXml.cpp
- #include "XercesParserXml.h"
- #include <xercesc/parsers/XercesDOMParser.hpp>
- #include <xercesc/dom/DOM.hpp>
- #include <xercesc/sax/HandlerBase.hpp>
- #include <xercesc/util/XMLString.hpp>
- #include <xercesc/util/PlatformUtils.hpp>
- #include <xercesc/framework/MemBufInputSource.hpp>
- #if defined(XERCES_NEW_IOSTREAMS)
- #include <iostream>
- #else
- #include <iostream>
- #include <iostream.h>
- #endif
- #include <vector>
- XERCES_CPP_NAMESPACE_USE
- DOMNode* getNode(DOMNode* node, const char* nodeName)
- {
- //char* ptr = (char *)nodeName;
- char ptr[4096] = {0};
- sprintf(ptr, "%s", nodeName);
- if (NULL == ptr)
- return NULL;
- char* d = ".";
- char* p = NULL;
- p = strtok(ptr, d);
- std::vector<std::string> vec;
- while (p)
- {
- //printf("name: %s/n", p);
- vec.push_back(p);
- p = strtok(NULL, d);
- }
- DOMNode* child;
- DOMNode* curNode = node;
- for (unsigned int i = 1; i < vec.size(); i++)
- {
- //std::cout << vec[i] << std::endl;
- if (0 == curNode) {
- return NULL;
- }
- for (child = curNode->getFirstChild(); child != 0; child = child->getNextSibling()) { // have no child ???
- char *name = XMLString::transcode(child->getNodeName());
- if (vec[i] == name) {
- //printf("vec[%d]: %s/tname: %s/n", i, vec[i].c_str(), name);
- XMLString::release(&name);
- curNode = child;
- break;
- }
- XMLString::release(&name);
- if (child == curNode->getLastChild()) {
- std::cout << "such node isn't exist" << std::endl;
- return NULL;
- }
- }
- }
- return curNode;
- }
- class XStr
- {
- public :
- // -----------------------------------------------------------------------
- // Constructors and Destructor
- // -----------------------------------------------------------------------
- XStr(const char* const toTranscode)
- {
- // Call the private transcoding method
- fUnicodeForm = XMLString::transcode(toTranscode);
- }
- ~XStr()
- {
- XMLString::release(&fUnicodeForm);
- }
- // -----------------------------------------------------------------------
- // Getter methods
- // -----------------------------------------------------------------------
- const XMLCh* unicodeForm() const
- {
- return fUnicodeForm;
- }
- private :
- // -----------------------------------------------------------------------
- // Private data members
- //
- // fUnicodeForm
- // This is the Unicode XMLCh format of the string.
- // -----------------------------------------------------------------------
- XMLCh* fUnicodeForm;
- };
- #define X(str) XStr(str).unicodeForm()
- bool XercesParserXml::has(const std::string& srcBytes, const std::string& node) const
- {
- // init
- try {
- XMLPlatformUtils::Initialize();
- }
- catch (const XMLException& toCatch) {
- char* message = XMLString::transcode(toCatch.getMessage());
- std::cout << "Error during initialization! :/n"
- << message << "/n";
- XMLString::release(&message);
- return false;
- }
- // 1. load the right xml bytes from signal tree
- XercesDOMParser* parser = new XercesDOMParser();
- if (NULL == parser) {
- return false;
- }
- parser->setValidationScheme(XercesDOMParser::Val_Always);
- parser->setDoNamespaces(true); // optional
- ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
- parser->setErrorHandler(errHandler);
- InputSource* pInputSource = new MemBufInputSource((XMLByte *)srcBytes.c_str(), srcBytes.size(), X("GUID"));
- if (NULL == pInputSource) {
- delete parser;
- delete errHandler;
- return false;
- }
- // 2. parser the xml bytes to a DOM tree
- parser->parse(*pInputSource);
- DOMDocument* doc = parser->getDocument();
- if (NULL == doc) {
- delete parser;
- delete errHandler;
- delete pInputSource;
- return false;
- }
- // 3. find node of parameter in DOM tree
- DOMElement* rootElem = NULL;
- rootElem = doc->getDocumentElement();
- DOMNode* testNode = NULL;
- testNode = getNode(rootElem, node.c_str());
- // release source
- delete parser;
- delete errHandler;
- delete pInputSource;
- //doc->release();
- if (testNode == NULL) {
- return false;
- }
- else {
- return true;
- }
- }
- std::string XercesParserXml::get(const std::string& srcBytes, const std::string& node) const
- {
- // init
- try {
- XMLPlatformUtils::Initialize();
- }
- catch (const XMLException& toCatch) {
- char* message = XMLString::transcode(toCatch.getMessage());
- std::cout << "Error during initialization! :/n"
- << message << "/n";
- XMLString::release(&message);
- return "";
- }
- // 1. load the right xml bytes from signal tree
- XercesDOMParser* parser = new XercesDOMParser();
- if (NULL == parser) {
- return "";
- }
- parser->setValidationScheme(XercesDOMParser::Val_Always);
- parser->setDoNamespaces(true); // optional
- ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
- parser->setErrorHandler(errHandler);
- InputSource* pInputSource = new MemBufInputSource((XMLByte *)srcBytes.c_str(), srcBytes.size(), X("GUID"));
- if (NULL == pInputSource) {
- delete parser;
- delete errHandler;
- return "";
- }
- // 2. parser the xml bytes to a DOM tree
- parser->parse(*pInputSource);
- DOMDocument* doc = parser->getDocument();
- if (NULL == doc) {
- delete parser;
- delete errHandler;
- delete pInputSource;
- return "";
- }
- // 3. find node of parameter in DOM tree
- DOMElement* rootElem = NULL;
- rootElem = doc->getDocumentElement();
- DOMNode* testNode = NULL;
- testNode = getNode(rootElem, node.c_str());
- // get content
- std::string result;
- char* nodeValue = NULL;
- if (testNode) {
- nodeValue = XMLString::transcode(testNode->getTextContent());
- result = nodeValue;
- XMLString::release(&nodeValue);
- }
- // release source
- delete parser;
- delete errHandler;
- delete pInputSource;
- //doc->release();
- return result;
- }
- bool XercesParserXml::set(std::string& srcBytes, const std::string& node, const std::string& value)
- {
- // init
- try {
- XMLPlatformUtils::Initialize();
- }
- catch (const XMLException& toCatch) {
- char* message = XMLString::transcode(toCatch.getMessage());
- std::cout << "Error during initialization! :/n"
- << message << "/n";
- XMLString::release(&message);
- return false;
- }
- // 1. load the right xml bytes from signal tree
- XercesDOMParser* parser = new XercesDOMParser();
- if (NULL == parser) {
- return false;
- }
- parser->setValidationScheme(XercesDOMParser::Val_Always);
- parser->setDoNamespaces(true); // optional
- ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
- parser->setErrorHandler(errHandler);
- InputSource* pInputSource = new MemBufInputSource((XMLByte *)srcBytes.c_str(), srcBytes.size(), X("GUID"));
- if (NULL == pInputSource) {
- delete parser;
- delete errHandler;
- return false;
- }
- // 2. parser the xml bytes to a DOM tree
- parser->parse(*pInputSource);
- DOMDocument* doc = parser->getDocument();
- if (NULL == doc) {
- delete parser;
- delete errHandler;
- delete pInputSource;
- return false;
- }
- // 3. find node of parameter in DOM tree
- DOMElement* rootElem = NULL;
- rootElem = doc->getDocumentElement();
- DOMNode* testNode = NULL;
- testNode = getNode(rootElem, node.c_str());
- // 4. set new content
- if (testNode) {
- testNode->setTextContent(X(value.c_str()));
- }
- // 5. serialize DOM tree and save it
- char* result;
- DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(X("Core"));
- if (NULL == impl) {
- XERCES_STD_QUALIFIER cerr << "Requested implementation is not supported" << XERCES_STD_QUALIFIER endl;
- XMLPlatformUtils::Terminate();
- delete parser;
- delete errHandler;
- delete pInputSource;
- return false;
- }
- DOMWriter* theSerializer = ((DOMImplementationLS*)impl)->createDOMWriter();
- if (NULL == theSerializer) {
- delete parser;
- delete errHandler;
- delete pInputSource;
- return false;
- }
- if (theSerializer->canSetFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true))
- theSerializer->setFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true);
- if (theSerializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true))
- theSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
- XMLCh* unicodeStr = theSerializer->writeToString(*rootElem);
- result = XMLString::transcode(unicodeStr);
- srcBytes = result;
- //printf("result: %s/n", result);
- XMLString::release(&unicodeStr);
- XMLString::release(&result);
- // release source
- theSerializer->release();
- delete parser;
- delete errHandler;
- delete pInputSource;
- return true;
- }
- bool XercesParserXml::del(std::string& srcBytes, const std::string& node)
- {
- // init
- try {
- XMLPlatformUtils::Initialize();
- }
- catch (const XMLException& toCatch) {
- char* message = XMLString::transcode(toCatch.getMessage());
- std::cout << "Error during initialization! :/n"
- << message << "/n";
- XMLString::release(&message);
- return false;
- }
- // 1. load the right xml bytes from signal tree
- XercesDOMParser* parser = new XercesDOMParser();
- if (NULL == parser) {
- return false;
- }
- parser->setValidationScheme(XercesDOMParser::Val_Always);
- parser->setDoNamespaces(true); // optional
- ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
- parser->setErrorHandler(errHandler);
- InputSource* pInputSource = new MemBufInputSource((XMLByte *)srcBytes.c_str(), srcBytes.size(), X("GUID"));
- if (NULL == pInputSource) {
- delete parser;
- delete errHandler;
- return false;
- }
- // 2. parser the xml bytes to a DOM tree
- parser->parse(*pInputSource);
- DOMDocument* doc = parser->getDocument();
- if (NULL == doc) {
- delete parser;
- delete errHandler;
- delete pInputSource;
- return false;
- }
- // 3. find node of parameter in DOM tree
- DOMElement* rootElem = NULL;
- rootElem = doc->getDocumentElement();
- DOMNode* testNode = NULL;
- testNode = getNode(rootElem, node.c_str());
- if (NULL == testNode) {
- delete parser;
- delete errHandler;
- delete pInputSource;
- return false;
- }
- // 4. remove identifier node from DOM tree
- DOMNode* parentNode = testNode->getParentNode();
- DOMNode* oldNode = parentNode->removeChild(testNode);
- oldNode->release();
- // 5. serialize DOM tree and save it
- char* result;
- DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(X("Core"));
- if (NULL == impl) {
- XERCES_STD_QUALIFIER cerr << "Requested implementation is not supported" << XERCES_STD_QUALIFIER endl;
- XMLPlatformUtils::Terminate();
- delete parser;
- delete errHandler;
- delete pInputSource;
- return false;
- }
- DOMWriter* theSerializer = ((DOMImplementationLS*)impl)->createDOMWriter();
- if (NULL == theSerializer) {
- delete parser;
- delete errHandler;
- delete pInputSource;
- return false;
- }
- if (theSerializer->canSetFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true))
- theSerializer->setFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true);
- if (theSerializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true))
- theSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
- XMLCh* unicodeStr = theSerializer->writeToString(*rootElem);
- result = XMLString::transcode(unicodeStr);
- srcBytes = result;
- //printf("result: %s/n", result);
- XMLString::release(&unicodeStr);
- XMLString::release(&result);
- // release source
- theSerializer->release();
- delete parser;
- delete errHandler;
- delete pInputSource;
- return true;
- }
- int main()
- {
- char* xmlFile = "x2.xml";
- char buf[4096] = {0};
- FILE* fp = fopen(xmlFile, "rb");
- if (!fp)
- {
- perror(xmlFile);
- exit(1);
- }
- size_t size;
- size = fread(buf, 1, sizeof(buf), fp);
- fclose(fp);
- std::cout << "size to be parser: " << size << std::endl;
- std::string srcDocBytes;
- srcDocBytes.assign(buf, size);
- std::string backup = srcDocBytes;
- XercesParserXml xml;
- bool flag = false;
- char testNode[1000] = {0};
- //其中各结点以“.”分隔,格式:root.child.grandson
- sprintf(testNode, "%s", "SendRoutingInfoRes.imsi");
- std::string result;
- for (int i = 0; i < 1; i++)
- {
- srcDocBytes = backup;
- printf("/nfind node test ... /n");
- flag = xml.has(srcDocBytes, testNode);
- printf("/nget node test .../n");
- result = xml.get(srcDocBytes, testNode);
- printf("get value: %s/n", result.c_str());
- printf("/nset node test .../n");
- xml.set(srcDocBytes, testNode, "gnu means gnu not unix");
- printf("new content: %s/n", srcDocBytes.c_str());
- printf("/nremove test .../n");
- xml.del(srcDocBytes, testNode);
- printf("after del operation: %s/n", srcDocBytes.c_str());
- }
- if (flag) {
- printf("%s has found/n", testNode);
- }
- else {
- printf("%s hasn't found/n", testNode);
- }
- }
从网上下了一段操作xml文件的代码,这段代码可以修改、删除、访问xml中的一个节点,感觉不是很有用,因为我想找的是能根据xml文件中元素的名称得到元素值的基本方法,根据元素名和该元素的属性名得到属性值的基本方法。
既然已经把代码下下来了,就运行了一下,结果报错了,调试的时候发现是引用KERNEL32.DLL的时候出错了,这个错误有些奇怪,出错的代码是parser->parse(*pInputSource);这一行,经过观察发现其他的函数也有与这段完全相同的代码,但是其他函数为什么没有出错呢?为什么完全相同的一段代码放在这里不会错,放在那里就报错了?
花了很多时间琢磨,终于找到原因了,那段代码本身是没有错误的,直接原因是main函数对子函数的调用顺序导致的,实质原因是,几个子函数对资源释放的不彻底导致的,可以这样类比,一个函数set去改写一个文本文件text,set改写了text后,没有释放资源,另一个函数del又去删除text,这时就发生资源访问冲突了。