⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xml.cpp

📁 这是一个能够自动生成文档的程序
💻 CPP
字号:

#include "stdafx.h"
#include "Xml.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

BEGIN_TEST_DUMP(CXml)
    TEST_DUMP(mFilePath)
END_TEST_DUMP()


CXml::CXml(int iNotesCount/*=0*/)
{
    mpRootNode = NULL;
	if(iNotesCount>0)
		InitNodesMap(iNotesCount);
}

CXml::~CXml()
{
    delete mpRootNode;
}

NOTEST
void CXml::InitNodesMap(int iNotesCount)
{
	int count = iNotesCount*30/100;
	count = (count/2) * 2 + 1;
	mNodesMap.InitHashTable(count);
}


BOOL CXml::Open(LPCTSTR iFilePath)
{
	mFilePath = iFilePath;

	HANDLE hFile = ::CreateFile(iFilePath, GENERIC_READ | GENERIC_WRITE, 0, 
		NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if(hFile == INVALID_HANDLE_VALUE)
		return FALSE;
	
	int fileSize = ::GetFileSize(hFile, NULL);
    HANDLE hMapFile = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, fileSize+1, NULL); 
	if(hMapFile == NULL)
	{
		::CloseHandle(hFile);
		return FALSE;
	}

	LPVOID pViewOfFile = ::MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, 0);
    if(pViewOfFile == NULL)
	{
		::CloseHandle(hFile);
		::CloseHandle(hMapFile);
		return FALSE;
	}

	char* pText = (char*)pViewOfFile;
	pText[fileSize] = '\0';
    TEST_TRACE(pText);

	ParseXmlFile(pText);

	//释放资源
	::UnmapViewOfFile(pViewOfFile);
	::CloseHandle(hMapFile);
	::CloseHandle(hFile);

	return TRUE;
}

BOOL CXml::Save(LPCTSTR iFilePath)
{
	CFile file;
	BOOL success;
	if(iFilePath == NULL)
		success = file.Open(mFilePath, CFile::modeCreate|CFile::modeWrite);
	else
		success = file.Open(iFilePath, CFile::modeCreate|CFile::modeWrite);
	
	if(!success)
		return FALSE;

	file.Write(XML_HEADER, strlen(XML_HEADER));

    CString text;
	if(mpRootNode != NULL)
		mpRootNode->GetFullText(text);

	file.Write(text, text.GetLength());
	file.Close();
	
	return TRUE;
}

BOOL CXml::ParseXmlFile(char* ipText)
{
	BOOL isStr = FALSE; //是否正在读取""内的字符串

	CList<CXmlNode*, CXmlNode*> list;  //临时保存节点,相当于堆栈
	CList<CXmlNode*, CXmlNode*> list2;  //临时保存节点,用于在载入完成后保存到影射表
	BOOL readingContent = FALSE; //是否正在读取内容  
    CString content;    //保存一个标签的内容
	BOOL begin = FALSE; //忽略前言区

	while(TRUE)
	{
		char ch = *ipText;
		if(ch == '\0') break;

        if(ch == '<') //一个标签开始,读取标签
		{
            CString tagStr;
			UINT tagType;
			begin = ParseTag(ipText, tagStr, tagType, begin);

			if(tagType == CXml::TAG_BEGIN) //新节点
			{
				CXmlNode* pFatherNode = NULL;
				if(!list.IsEmpty())
					pFatherNode = list.GetTail();

				CXmlNode* pNewNode = new CXmlNode(pFatherNode);
				pNewNode->Init(pFatherNode, tagStr);

				//新节点在临时列表中保存
				list.AddTail(pNewNode);
				list2.AddTail(pNewNode);

				if(pFatherNode == NULL) //根节点
				{
					ASSERT(mpRootNode == NULL);
					mpRootNode = pNewNode;
				}
				else
				{
					//如果加入成功,由父节点删除
					if(!pFatherNode->AddChildNode(pNewNode))
					{
						delete pNewNode;
						return FALSE;
					}
				}
			}
			else if(tagType == CXml::TAG_END)
			{
				ASSERT(!list.IsEmpty());
				if(!list.IsEmpty())
				{
				    CXmlNode* pTailNode = list.GetTail();
					pTailNode->SetTagEnd(tagStr);
                    if(readingContent)
					    pTailNode->SetContent(content);
					TEST_TRACE(pTailNode);
					list.RemoveTail();
				}
			}
			else if(tagType == CXml::TAG_FULL)
			{
				CXmlNode* pFatherNode = NULL;
				if(!list.IsEmpty())
					pFatherNode = list.GetTail();

				CXmlNode* pNewNode = new CXmlNode(pFatherNode);
				pNewNode->Init(pFatherNode, tagStr);

				//自关闭节点只保存到列表2
				list2.AddTail(pNewNode);

				if(pFatherNode == NULL) //根节点
				{
					ASSERT(mpRootNode == NULL);
					mpRootNode = pNewNode;
				}
				else
				{
					//如果加入成功,由父节点删除
					if(!pFatherNode->AddChildNode(pNewNode))
					{
						delete pNewNode;
						return FALSE;
					}
				}

				TEST_TRACE(pNewNode);
			}

			readingContent = (tagType==CXml::TAG_BEGIN);
		}
        else if(readingContent)
		{
            content.Empty();
			ReadContent(ipText, content);
		}
		else
		{
		    ipText++;
		}
	}

	ASSERT(list.IsEmpty());

	//保存到影射表
	int count = list2.GetCount();
    InitNodesMap(count);

	POSITION pos = list2.GetHeadPosition();
	while(pos != NULL)
	{
		CXmlNode* pNode = list2.GetNext(pos);
		InsertIntoMap(pNode);
	}

	return TRUE;
}

BOOL CXml::ParseTag(char*& ipText, CString& oTagStr, UINT& oTagType, BOOL iBegin)
{
	oTagType = CXml::TAG_UNKNOW;
	char pre = '\0';
	int index = 0;
	BOOL result = TRUE;

	ASSERT(ipText != NULL);

	while(TRUE)
	{
		char ch = *ipText;
		if(ch == '\0') break;

        ASSERT(index>0 || ch=='<');
		oTagStr += ch;

		if(index == 1)
		{
			if(ch == '/')
			    oTagType = CXml::TAG_END;
			else if(ch == '?' && !iBegin)
				result = FALSE;
		}

		if(ch == '>')
		{
			if(pre == '/')
				oTagType = CXml::TAG_FULL;
			ipText++;
			break;
		}

		pre = ch;
		ipText++;
		index++;
	}

	if(!result)
        oTagType = CXml::TAG_UNKNOW;
    else if(oTagType == CXml::TAG_UNKNOW)
		oTagType = CXml::TAG_BEGIN;

	return result;
}

BOOL CXml::ReadContent(char*& ipText, CString& oContent)
{
	while(TRUE)
	{
		char ch = *ipText;
		if(ch == '\0') break;

		if(ch == '<')
			break;

		ipText++;
		oContent += ch;
	}

	return TRUE;
}

BOOL CXml::AddNode(LPCTSTR iTagBegin, 
				   LPCTSTR iPath, 
		           LPCTSTR iContent, 
				   LPCTSTR iTagEnd)
{
    if(iTagBegin == NULL || iTagEnd == NULL)
		return FALSE;

    CXmlNode* pFatherNode = NULL;
	if(iPath != NULL) 
		pFatherNode = FindNode(iPath);
	
	CXmlNode* pNewNode = CreateNode(iTagBegin, iContent, iTagEnd, pFatherNode);
	if(pFatherNode != NULL)
	{
		//如果成功加入,由父节点删除
		if(!pFatherNode->AddChildNode(pNewNode))
		{
			delete pNewNode;
			return FALSE;
		}
	}
	else
	{
		ASSERT(mpRootNode == NULL);
		mpRootNode = pNewNode;
	}

	InsertIntoMap(pNewNode);
	return TRUE;
}

CXmlNode* CXml::CreateNode(LPCTSTR iTagBegin,
					       LPCTSTR iContent/*=NULL*/, 
				           LPCTSTR iTagEnd/*=NULL*/,
					       CXmlNode* pFatherNode/*=NULL*/)
{
	//由AddNode负责删除
	CXmlNode* pNewNode = new CXmlNode();
	pNewNode->Init(pFatherNode, iTagBegin);

	//如果iTagEnd为NULL,则iContent必须为NULL
	ASSERT(iContent == NULL || iTagEnd != NULL);
	
	if(iContent != NULL && iTagEnd != NULL)
		pNewNode->SetContent(iContent);
	if(iTagEnd != NULL)
		pNewNode->SetTagEnd(iTagEnd);

	return pNewNode;
}

CXmlNode* CXml::FindNode(LPCTSTR iFullPath)
{
	ASSERT(iFullPath != NULL);
	void* pNode = NULL;
	mNodesMap.Lookup(iFullPath, pNode);

	TEST_TRACE((CXmlNode*)pNode);
	return (CXmlNode*)pNode;
}

NOTEST
void CXml::InsertIntoMap(CXmlNode* ipNode)
{
	ASSERT(ipNode != NULL);
	CString key = ipNode->GetPath() + ipNode->GetTagBegin();
	mNodesMap.SetAt(key, ipNode);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -