现在的位置: 首页 > 综合 > 正文

使用 ACEXML 来解析一个 xml 文件

2019年01月10日 ⁄ 综合 ⁄ 共 10021字 ⁄ 字号 评论关闭

本段代码通过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", m_value.c_str(), 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 *localName,
                             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 *publicId,
                                   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 start, size_t length)
{
	m_value = string(cdata);	
}

void CXMLParse::startElement(const ACEXML_Char *uri, const ACEXML_Char *name, const ACEXML_Char *qName, ACEXML_Attributes *alist)
{
	
	CTree* node = new CTree(CTree::NOTLEAF, name);
	m_stack.push(node);
}

void CXMLParse::endElement(const ACEXML_Char *uri,const ACEXML_Char *name, 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 *publicID,
                                    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, "%s: line: %d col: %d ",
				(this->locator_->getSystemId() == 0 ? this->fileName_ : this->locator_->getSystemId()),
				this->locator_->getLineNumber(),
				this->locator_->getColumnNumber()));
	ex.print();*/

}

void CXMLParse::warning(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();*/
}

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;
}

抱歉!评论已关闭.