📄 xml.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 + -