www.pudn.com > ParseXML.rar > XmlFile.cpp


#include "StdAfx.h" 
#include "xmlfile.h" 
 
//#include  
 
///////////////////////////////////////////////////////////////////// 
// class CDataBuffer 
 
CDataBuffer::CDataBuffer() 
{ 
	m_pDataBuffer = NULL; 
	m_nDataSize = 0; 
	m_nReadPos = 0; 
} 
 
CDataBuffer::~CDataBuffer() 
{ 
	if(m_pDataBuffer != NULL) 
	{ 
		delete m_pDataBuffer; 
	} 
} 
 
BOOL CDataBuffer::CreateFromFile(LPCTSTR lpszFilePath) 
{ 
	CFile file; 
	if(!file.Open(lpszFilePath, CFile::modeRead)) 
	{ 
		return FALSE; 
	} 
 
	if(m_pDataBuffer != NULL)	delete m_pDataBuffer; 
	m_nDataSize = (DWORD)file.GetLength(); 
	m_pDataBuffer = new BYTE[m_nDataSize]; 
 
	if(file.Read(m_pDataBuffer, m_nDataSize) != m_nDataSize) 
	{ 
		delete m_pDataBuffer; 
		file.Close(); 
		return FALSE; 
	} 
	m_nReadPos = 0; 
 
	return TRUE; 
} 
 
void CDataBuffer::FreeBuffer() 
{ 
	if(m_pDataBuffer != NULL) 
	{ 
		delete m_pDataBuffer; 
	} 
 
	m_nDataSize = 0; 
	m_nReadPos = 0; 
} 
 
BOOL CDataBuffer::ReadByte(BYTE& ch) 
{ 
	if(m_nReadPos < m_nDataSize) 
	{ 
		ch = m_pDataBuffer[m_nReadPos]; 
		m_nReadPos++; 
		return TRUE; 
	} 
 
	return FALSE; 
} 
 
void CDataBuffer::GoBack(DWORD nCount) 
{ 
	if(m_nReadPos >= (DWORD)nCount)	 
		m_nReadPos -= nCount; 
	else							 
		m_nReadPos = 0; 
} 
 
void CDataBuffer::CopyData(void* pBuffer, DWORD nPos, DWORD nLen) 
{ 
	if(pBuffer != NULL &&  
		m_pDataBuffer != NULL && 
		nPos + nLen < m_nDataSize) 
	{ 
		memcpy(pBuffer, m_pDataBuffer + nPos, nLen); 
	} 
} 
 
 
///////////////////////////////////////////////////////////////////// 
// class CXmlTag 
 
CXmlTag::CXmlTag() 
{ 
	m_pBuffer = NULL; 
	m_nTagType = -1; 
} 
 
CXmlTag::~CXmlTag() 
{ 
	if(m_pBuffer != NULL)	 
	{ 
		delete m_pBuffer; 
	} 
} 
 
BOOL CXmlTag::IsXmlVersionTag() 
{ 
	if(m_pBuffer == NULL)							 
		return FALSE; 
	if(strstr((char *)m_pBuffer, "')  
		{ 
			break; 
		} 
	} 
	DWORD to = data.GetPosition(); 
	m_pBuffer = new BYTE[to - from + 1]; 
	data.CopyData(m_pBuffer, from, to - from); 
	m_pBuffer[to - from] = '\0'; 
 
	if(m_nTagType == 2) 
	{ 
		if(to - from > 2) 
		{ 
			if(m_pBuffer[1] == '/') 
			{ 
				m_nTagType = 4; 
			} 
			else if(m_pBuffer[to - from - 2] == '/') 
			{ 
				m_nTagType = 3; 
			} 
		} 
		else 
		{ 
			m_nTagType = -1; 
		} 
	} 
 
	return m_nTagType != -1; 
} 
 
BOOL CXmlTag::IsSameName(char* name) 
{ 
	if(m_pBuffer != NULL && strlen((char*)m_pBuffer) - strlen(name) >= 2) 
	{ 
		if(strstr((char*)m_pBuffer, name) == (char*)(m_pBuffer + 1) &&  
			(  m_pBuffer[strlen(name) + 1] == ' ' ||  
			   m_pBuffer[strlen(name) + 1] == '/' ||  
			   m_pBuffer[strlen(name) + 1] == '>' 
			 )) 
		{ 
			return TRUE; 
		} 
	} 
 
	return FALSE; 
} 
 
int CXmlTag::GetAttributeLen(char* name) 
{ 
	if(m_pBuffer != NULL && (m_nTagType == 2 || m_nTagType == 3)) 
	{ 
		char* substr = new char[strlen(name) + 2]; 
		strcpy(substr, name); 
		substr[strlen(name)] = '='; 
		substr[strlen(name) + 1] = '\0'; 
 
		char* str = strstr((char *)m_pBuffer, substr); 
		if(str != NULL) 
		{ 
			int pos = 0; 
			while(str[pos] != '\0' &&  
				str[pos] != '\t' &&  
				str[pos] != ' ' &&  
				str[pos] != '/' &&  
				str[pos] != '>')  
				pos++; 
 
			return pos; 
		} 
	} 
 
	return 0; 
} 
 
int CXmlTag::GetAttribute(char* name, char*value, int len) 
{ 
	if(m_pBuffer != NULL && (m_nTagType == 2 || m_nTagType == 3)) 
	{ 
		char* substr = new char[strlen(name) + 2]; 
		strcpy(substr, name); 
		substr[strlen(name)] = '='; 
		substr[strlen(name) + 1] = '\0'; 
 
		char* str = strstr((char *)m_pBuffer, substr); 
		if(str != NULL) 
		{ 
			int pos = 0; 
			while(str[pos] != '\0' &&  
				str[pos] != '\t' &&  
				str[pos] != ' ' &&  
				str[pos] != '/' &&  
				str[pos] != '>'&& 
				pos < len - 1)  
			{ 
				value[pos] = str[pos]; 
				pos++; 
			} 
			value[pos] = '\0'; 
			return pos; 
		} 
	} 
 
	return 0; 
} 
 
int CXmlTag::GetValueLen() 
{ 
	CXmlTag* pTag = (CXmlTag *)m_pLeftNode; 
	while(pTag != NULL && pTag->m_nTagType != 0) pTag = (CXmlTag *)pTag->m_pRightNode; 
 
	if(pTag != 0 && pTag->m_pBuffer != NULL) 
	{ 
		return (int)strlen((char *)pTag->m_pBuffer); 
	} 
 
	return 0; 
} 
 
int CXmlTag::GetValue(char* value, int len) 
{ 
	CXmlTag* pTag = (CXmlTag *)m_pLeftNode; 
	while(pTag != NULL && pTag->m_nTagType != 0) pTag = (CXmlTag *)pTag->m_pRightNode; 
 
	if(pTag != 0 && pTag->m_pBuffer != NULL) 
	{ 
		int i = 0; 
		for(; i < len && pTag->m_pBuffer[i] != '\0'; i++) 
		{ 
			value[i] = pTag->m_pBuffer[i]; 
		} 
		value[i] = '\0'; 
		return i; 
	} 
 
	return 0; 
} 
 
CString CXmlTag::GetValue() 
{ 
	int len = GetValueLen(); 
	char* buffer = new char[len + 1]; 
	GetValue(buffer, len); 
 	CStringA strTmpA = buffer; 
	CString strTmp = CA2T(buffer); 
	return strTmp; 
} 
 
///////////////////////////////////////////////////////////////////// 
// class CXmlFile 
 
CXmlFile::CXmlFile(void) 
{ 
} 
 
CXmlFile::~CXmlFile(void) 
{ 
} 
 
BOOL CXmlFile::Open(LPCTSTR lpszFilePath) 
{ 
	CDataBuffer data; 
 
	if(!data.CreateFromFile(lpszFilePath)) 
	{ 
		return FALSE; 
	} 
 
	if(!ParseXml(data)) 
	{ 
		return FALSE; 
	} 
 
	return TRUE; 
} 
 
void CXmlFile::Close() 
{ 
	m_XmlNodeTree.FreeTree(); 
} 
 
BOOL CXmlFile::ParseXml(CDataBuffer& data) 
{ 
	CXmlTag	tag; 
 
	if(!tag.Read(data)) 
	{ 
		return FALSE; 
	} 
 
	if(!tag.IsXmlVersionTag()) 
	{ 
		return FALSE; 
	} 
 
	if(!ParseXml(data, m_XmlNodeTree.GetRootNode())) 
	{ 
		return FALSE; 
	} 
 
	return TRUE; 
} 
 
BOOL CXmlFile::ParseXml(CDataBuffer& data, CNode* pParentNode) 
{ 
	while(data.IsEOF()) 
	{ 
		CXmlTag* tag = new CXmlTag(); 
		//读入一个TAG 
		if(tag->Read(data)) 
		{ 
			BYTE nTagType = tag->GetTagType(); 
			if(nTagType == 0 || nTagType == 3) 
			{ 
				m_XmlNodeTree.InsertChildNode(tag, pParentNode); 
			} 
			else if(nTagType == 1) 
			{ 
				//丢弃不要 
				delete tag; 
			} 
			else if(nTagType == 2) 
			{ 
				m_XmlNodeTree.InsertChildNode(tag, pParentNode); 
				if(!ParseXml(data, tag)) 
				{ 
					delete tag; 
					return FALSE; 
				} 
			} 
			else //nTagType == 4 
			{ 
				delete tag; 
				return TRUE; 
			} 
		} 
		else 
		{ 
			delete tag; 
			return FALSE; 
		} 
	} 
 
	return TRUE; 
} 
 
CXmlTag* CXmlFile::GetRootElement() 
{  
	return (CXmlTag *)m_XmlNodeTree.GetRootNode()->m_pLeftNode;  
} 
 
int CXmlFile::GetChildElementCount(CXmlTag* pParent) 
{ 
	int n = 0; 
	if(pParent != NULL) 
	{ 
		CNode* p = pParent->m_pLeftNode; 
		while(p != NULL) 
		{ 
			n++; 
			p = p->m_pRightNode; 
		} 
	} 
 
	return n; 
} 
 
CXmlTag* CXmlFile::GetChildElement(CXmlTag* pParent, int nIndex) 
{ 
	if(pParent != NULL) 
	{ 
		int n = 0; 
		CNode* p = pParent->m_pLeftNode; 
		while(p != NULL && n != nIndex) 
		{ 
			n++; 
			p = p->m_pRightNode; 
		} 
 
		return (CXmlTag *)p; 
	} 
 
	return NULL;	 
} 
 
CXmlTag* CXmlFile::FindChildElement(CXmlTag* pParent, char* name) 
{ 
	if(pParent != NULL && name != NULL) 
	{ 
		CXmlTag* p = (CXmlTag *)pParent->m_pLeftNode; 
		while(p != NULL && !p->IsSameName(name))  
		{ 
			p = (CXmlTag *)p->m_pRightNode; 
		} 
 
		return p; 
	} 
 
	return NULL; 
}