本段代码通过ACEXML来解析一个XML文件,并且生成了一棵树,树的存储采用孩子兄弟存储的方法。
ACEd.lib
ACEXMLd.lib
ACEXML_Parserd.lib
iphlpapi.lib
CTree
#pragma once #include "string" using namespace std; class CTree { public: typedef enum{LEAF = 0x00,NOTLEAF = 0x01} ATTRIBUTE; public: CTree(void); CTree(ATTRIBUTE attribute,string value); ~CTree(void); private: ATTRIBUTE m_attribute; string m_value; CTree* m_left; CTree* m_right; public: void addnode(CTree* children); void output(int indent); ATTRIBUTE getattribute(); string getvalue(); CTree* getleft(); CTree* getright(); int getchildnumber(); CTree* getfirstchild(); CTree* getnextchild(); CTree* getchild(int index); void destroy(); }; #include "Tree.h" CTree::CTree(void) { m_attribute = NOTLEAF; m_value = ""; m_left = NULL; m_right = NULL; } CTree::CTree(ATTRIBUTE attribute,string value) { m_attribute = attribute; m_value = value; m_left = NULL; m_right = NULL; } CTree::~CTree(void) { printf("destroy value=%s\n",m_value.c_str()); } CTree::ATTRIBUTE CTree::getattribute() { return m_attribute; } CTree* CTree::getleft() { return m_left; } CTree* CTree::getright() { return m_right; } string CTree::getvalue() { return m_value; } void CTree::destroy() { if (m_left != NULL) { m_left->destroy(); } if (m_right != NULL) { m_right->destroy(); } delete this; } void CTree::addnode(CTree* child) { if (m_left == NULL) { m_left = child; } else { CTree* ptemp = m_left; while(ptemp->m_right != NULL) { ptemp = ptemp->m_right; } ptemp->m_right = child; } } void CTree::output(int indent) { //printf("value=%s attri=%c this=%08X left=%08X right=%08X\n",m_value.c_str(),((m_attribute == LEAF) ? 'C' : 'P'),this,m_left,m_right); //printf("%s(deep=%d)\n",indent); printf("%s\n",m_value.c_str()); if (m_left != NULL) { indent++; for(int i=0; i<indent; i++) { printf("|____"); } m_left->output(indent); indent--; } if (m_right != NULL) { for(int i = 0; i < indent; i++) { printf("|____"); } m_right->output(indent); } } int CTree::getchildnumber() { int number = 0; if (m_left == NULL) { return number; } else { number++; CTree* temp = m_left; while(temp->m_right != NULL) { number++; temp = temp->m_right; } } return number; } CTree* CTree::getfirstchild() { return m_left; } CTree* CTree::getnextchild() { return m_right; } CTree* CTree::getchild(int index) { CTree* temp = NULL; bool find = false; int count = 1; if (index == 1) { find = true; temp = m_left; } else { temp = m_left; while(temp->m_right != NULL) { count++; if (count == index) { find = true; break; } temp = temp->m_right; } } if (find) { return temp; } else { temp = NULL; return temp; } }
CStack
#pragma once #include "Stack" class CTree; using namespace std; typedef stack<CTree*> STACK; class CStack { public: CStack(void); ~CStack(void); private: STACK m_stack; public: void push(CTree* node); CTree* pop(); CTree* get(); int size(); bool empty(); }; #include "Stack.h" CStack::CStack(void) { } CStack::~CStack(void) { } void CStack:: push(CTree* node) { m_stack.push(node); } CTree* CStack::pop() { CTree* node = NULL; if (!empty()) { node = get(); m_stack.pop(); } return node; } CTree* CStack::get() { CTree* node = NULL; if (!empty()) { node = m_stack.top(); } return node; } int CStack::size() { return m_stack.size(); } bool CStack::empty() { return m_stack.empty(); }
CXMLParse
#pragma once #include "ACEXML/common/DefaultHandler.h" #include "string" #include "Tree.h" #include "Stack.h" using namespace std; class CXMLParse : public ACEXML_DefaultHandler { public: CXMLParse(ACEXML_Char* fileName); virtual ~CXMLParse(void); public: // Methods inherited from ACEXML_ContentHandler. /* * Receive notification of character data. */ virtual void characters (const ACEXML_Char *ch,size_t start,size_t length); /* * Receive notification of the end of a document. */ virtual void endDocument (void); /* * Receive notification of the end of an element. */ virtual void endElement (const ACEXML_Char *namespaceURI,const ACEXML_Char *localName,const ACEXML_Char *qName); /* * End the scope of a prefix-URI mapping. */ virtual void endPrefixMapping (const ACEXML_Char *prefix); /* * Receive notification of ignorable whitespace in element content. */ virtual void ignorableWhitespace (const ACEXML_Char *ch,int start,int length); /* * Receive notification of a processing instruction. */ virtual void processingInstruction (const ACEXML_Char *target,const ACEXML_Char *data); /* * Receive an object for locating the origin of SAX document events. */ virtual void setDocumentLocator (ACEXML_Locator *locator) ; /* * Receive notification of a skipped entity. */ virtual void skippedEntity (const ACEXML_Char *name); /* * Receive notification of the beginning of a document. */ virtual void startDocument (void); /* * Receive notification of the beginning of an element. */ virtual void startElement (const ACEXML_Char *namespaceURI,const ACEXML_Char *qName,ACEXML_Attributes *atts); /* * Begin the scope of a prefix-URI Namespace mapping. */ virtual void startPrefixMapping (const ACEXML_Char *prefix,const ACEXML_Char *uri); // *** Methods inherit from ACEXML_DTDHandler. /* * Receive notification of a notation declaration event. */ virtual void notationDecl (const ACEXML_Char *name,const ACEXML_Char *publicId,const ACEXML_Char *systemId); /* * Receive notification of an unparsed entity declaration event. */ virtual void unparsedEntityDecl (const ACEXML_Char *name,const ACEXML_Char *systemId,const ACEXML_Char *notationName); // Methods inherit from ACEXML_EnitityResolver. /* * Allow the application to resolve external entities. */ virtual ACEXML_InputSource *resolveEntity (const ACEXML_Char *publicId,const ACEXML_Char *systemId); // Methods inherit from ACEXML_ErrorHandler. /* * Receive notification of a recoverable error. */ virtual void error (ACEXML_SAXParseException &exception); /* * Receive notification of a non-recoverable error. */ virtual void fatalError (ACEXML_SAXParseException &exception); /* * Receive notification of a warning. */ virtual void warning (ACEXML_SAXParseException &exception); private: ACEXML_Char* fileName_; ACEXML_Locator* locator_; private: CTree *m_ptree; CStack m_stack; string m_value; }; #include "XMLParse.h" #include "ace/ACE.h" #include "ace/Log_Msg.h" CXMLParse::CXMLParse (ACEXML_Char* fileName) : fileName_(ACE::strnew(fileName)) { m_ptree = NULL; m_value = ""; } CXMLParse::~CXMLParse (void) { delete[] this->fileName_; if (m_ptree != NULL) { m_ptree->destroy(); } } void CXMLParse::characters(const ACEXML_Char *cdata,size_t length) { m_value = string(cdata); } void CXMLParse::startElement(const ACEXML_Char *uri,const ACEXML_Char *name,ACEXML_Attributes *alist) { CTree* node = new CTree(CTree::NOTLEAF,name); m_stack.push(node); } void CXMLParse::endElement(const ACEXML_Char *uri,const ACEXML_Char *qName) { CTree* node = m_stack.get(); if (node == NULL) return; if (node->getleft() == NULL && node->getright() == NULL)//如果栈顶的元素左右没有孩子,说明需要插入节点 { //生成叶子节点 CTree* newnode = new CTree(CTree::LEAF,m_value); //叶子节点的父亲节点出栈 node = m_stack.pop(); //设置叶子节点和父亲节点的关系 node->addnode(newnode); CTree* parentnode = m_stack.get(); if (parentnode == NULL) return; parentnode->addnode(node);//记录相互关系,但不用出栈 } else////如果栈顶的元素左右有孩子,说明仅仅需要修改指针关系 { CTree* newnode = m_stack.pop(); if (m_stack.empty()) { m_ptree = newnode; } else { CTree* node = m_stack.get(); node->addnode(newnode); } } } void CXMLParse::endDocument(void) { //test for display tree m_ptree->output(0); //test for get children number printf("*********************************************\n"); printf("childnumber = %d\n",m_ptree->getchildnumber()); printf("*********************************************\n"); //test for scan a parent's all children CTree* node = m_ptree->getfirstchild(); while(node != NULL) { printf("value=%s\n",node->getvalue().c_str()); node = node->getnextchild(); } //test for scan a parent's children printf("*********************************************\n"); for(int i = 0; i < m_ptree->getchildnumber(); i++) { CTree* node = m_ptree->getchild(i + 1); if (node != NULL) { printf("value=%s\n",node->getvalue().c_str()); } } } void CXMLParse::endPrefixMapping (const ACEXML_Char *prefix) { } void CXMLParse::ignorableWhitespace(const ACEXML_Char *,int,int) { } void CXMLParse::processingInstruction(const ACEXML_Char *target,const ACEXML_Char *data) { } void CXMLParse::setDocumentLocator(ACEXML_Locator * locator) { this->locator_ = locator; } void CXMLParse::skippedEntity(const ACEXML_Char *name) { } void CXMLParse::startDocument(void) { } void CXMLParse::startPrefixMapping(const ACEXML_Char * prefix,const ACEXML_Char * uri) { } void CXMLParse::notationDecl(const ACEXML_Char *name,const ACEXML_Char *publicID,const ACEXML_Char *systemID) { } void CXMLParse::unparsedEntityDecl(const ACEXML_Char *name,const ACEXML_Char *systemID,const ACEXML_Char *notationName) { } ACEXML_InputSource * CXMLParse::resolveEntity (const ACEXML_Char *,const ACEXML_Char *) { return 0; } void CXMLParse::error(ACEXML_SAXParseException & ex) { /*ACE_DEBUG((LM_DEBUG,"%s: line: %d col: %d ",(this->locator_->getSystemId() == 0 ? this->fileName_ : this->locator_->getSystemId()),this->locator_->getLineNumber(),this->locator_->getColumnNumber())); ex.print();*/ } void CXMLParse::fatalError(ACEXML_SAXParseException& ex) { /*ACE_DEBUG ((LM_DEBUG,this->locator_->getColumnNumber())); ex.print();*/ } void CXMLParse::warning(ACEXML_SAXParseException & ex) { /*ACE_DEBUG ((LM_DEBUG,this->locator_->getColumnNumber())); ex.print();*/ }
CDecodeXML
#pragma once #include "string" using namespace std; class CDecodeXML { public: CDecodeXML(void); ~CDecodeXML(void); public: bool decode(string xmlfilename); }; #include "DecodeXML.h" #include "ACEXML/common/FileCharStream.h" #include "ACEXML/parser/parser/Parser.h" #include "XMLParse.h" #include "ace/Auto_Ptr.h" CDecodeXML::CDecodeXML(void) { } CDecodeXML::~CDecodeXML(void) { } bool CDecodeXML::decode(string xmlfilename) { int result = true; ACEXML_Char* filename = (ACEXML_Char*)xmlfilename.c_str(); ACEXML_FileCharStream *fstm = 0; ACE_NEW_RETURN(fstm,ACEXML_FileCharStream(),!result); if (fstm->open(filename) != 0) { printf("Failed to open XML file: %s\n",filename); result = false; return result; } ACEXML_CharStream *stm = fstm; CXMLParse *handler = 0; ACE_NEW_RETURN(handler,CXMLParse(filename),!result); auto_ptr<ACEXML_DefaultHandler> cleanup_handler(handler); ACEXML_Parser parser; ACEXML_InputSource input(stm); parser.setContentHandler(handler); parser.setDTDHandler(handler); parser.setErrorHandler(handler); parser.setEntityResolver(handler); try { parser.parse(&input); } catch (const ACEXML_SAXException& ex) { ex.print(); printf("Exception occurred. Exiting...\n"); result = false; } return result; }
主函数测试:
#include "stdafx.h" #include "DecodeXML.h" int main(int argc,char* argv[]) { CDecodeXML decodexml; decodexml.decode("d:\\xml\\1.xml"); getchar(); return 0; }