C/C++读写解析xml文件,写的比较简单,读写解析测试了下,定位更新等操作懒得测试了,估计有很多可以优化的,欢迎各位阅读,也欢迎来讨论
/****************************************
文件名称:xmlfile.h
作者:木马小Z
创建日期:20210910
版本:V1.0
****************************************/
#include <iostream>
#include <string.h>
#define ERR_MES_1 "输入值不合法"
#define ERR_MES_2 "打开文件失败"
#define ERR_MES_3 "配置项不存在"
class XmlAttribute
{
public:
XmlAttribute();
~XmlAttribute();
std::string m_Name;
std::string m_Value;
XmlAttribute *m_pNext;
};
class XmlNode
{
public:
XmlNode();
~XmlNode();
std::string m_Name;
std::string m_Value;
XmlNode *m_pParent;
XmlNode *m_pPrev;
XmlNode *m_pNext;
XmlNode *m_pChild;
XmlAttribute *m_pAttribute;
};
class XmlFile
{
public:
XmlFile();
~XmlFile();
/****************************************
函数名称:ReadFile
参数列表:FilePathName 文件目录
用途 :读取ini文件
返回值 :成功true 失败false
****************************************/
bool ReadFile(const char *FilePathName);
/****************************************
函数名称:WriteFile
参数列表:FilePathName 文件目录
用途 :写入ini文件
返回值 :成功true 失败false
****************************************/
bool WriteFile(const char *FilePathName);
/****************************************
函数名称:AnalysisFile
参数列表:
用途 :解析ini文件
返回值 :成功true 失败false
****************************************/
bool AnalysisFile();
void LocateRoot();
bool LocateNode(XmlNode *pNode);
bool LocateParent();
bool LocatePrev();
bool LocateNext();
bool LocatepChild();
XmlNode *GetCurNode();
std::string GetCurNodeName();
std::string GetCurNodeValue();
XmlAttribute *GetCurNodeAttribute();
XmlNode *AddXmlNode(XmlNode *pParent, std::string Name, std::string Value);
bool UpdateXmlNode(XmlNode *pNode, std::string Name, std::string Value);
void DeleteXmlNode(XmlNode *pNode);
bool AddNodeAttribute(XmlNode *pNode, std::string AttributeName, std::string AttributeValue);
bool UpdateNodeAttribute(XmlNode *pNode, std::string AttributeName, std::string AttributeValue);
void DeleteNodeAttribute(XmlNode *pNode);
void DeleteNodeAttribute(XmlNode *pNode, std::string AttributeName);
friend void AnalysisXml(XmlNode *pParent, char *Buffer, long BufferSize);
friend void CreateNode(XmlNode *pNode, char *pValue);
friend void Trim(char *Buffer);
friend void NodeToBuffer(XmlNode *pNode, char *pBuffer, int Depth);
friend void DeleteNode(XmlNode *pNode);
friend void DeleteAttribute(XmlAttribute *pAttribute);
protected:
private:
char *m_pFileBuffur;
XmlNode *m_pRootNode;
XmlNode *m_pCurNode;
FILE *m_pFileHandle;
int m_LastErrCode;
std::string m_LastErrMes;
long m_FileSize;
};
void AnalysisXml(XmlNode *pParent, char *Buffer, long BufferSize);
void CreateNode(XmlNode *pNode, char *pValue);
void Trim(char *Buffer);
void NodeToBuffer(XmlNode *pNode, char *pBuffer, int Depth);
void DeleteNode(XmlNode *pNode);
void DeleteAttribute(XmlAttribute *pAttribute);
/****************************************
文件名称:xmlfile.cpp
作者:木马小Z
创建日期:20210910
版本:V1.0
****************************************/
#include "xmlfile.h"
#include <sys/stat.h>
XmlAttribute::XmlAttribute()
{
m_Name = "";
m_Value = "";
m_pNext = nullptr;
}
XmlAttribute::~XmlAttribute()
{
}
XmlNode::XmlNode()
{
m_Name = "";
m_Value = "";
m_pParent = nullptr;
m_pPrev = nullptr;
m_pNext = nullptr;
m_pChild = nullptr;
m_pAttribute = nullptr;
}
XmlNode::~XmlNode()
{
}
XmlFile::XmlFile()
{
m_pFileBuffur = nullptr;
m_pRootNode = nullptr;
m_pCurNode = nullptr;
m_pFileHandle = nullptr;
}
XmlFile::~XmlFile()
{
DeleteXmlNode(m_pRootNode);
delete[]m_pFileBuffur;
fclose(m_pFileHandle);
m_pFileBuffur = nullptr;
m_pRootNode = nullptr;
m_pCurNode = nullptr;
m_pFileHandle = nullptr;
}
bool XmlFile::ReadFile(const char *FilePathName)
{
if (!strcmp(FilePathName, ""))
{
m_LastErrCode = 1;
m_LastErrMes = ERR_MES_1;
return false;
}
if (!(m_pFileHandle = fopen(FilePathName, "r")))
{
m_LastErrCode = 2;
m_LastErrMes = ERR_MES_2;
return false;
}
struct stat FileStat;
stat(FilePathName, &FileStat);
m_FileSize = FileStat.st_size;
m_pFileBuffur = new char[m_FileSize];
memset(m_pFileBuffur, 0, m_FileSize);
fread(m_pFileBuffur, 1, m_FileSize, m_pFileHandle);
fclose(m_pFileHandle);
return true;
}
bool XmlFile::WriteFile(const char *FilePathName)
{
if (!strcmp(FilePathName, ""))
{
m_LastErrCode = 1;
m_LastErrMes = ERR_MES_1;
return false;
}
char FilePathNameBat[256] = { 0 };
strcpy(FilePathNameBat, FilePathName);
strcat(FilePathNameBat, ".bak");
FILE *FileXmlTemp = fopen(FilePathName, "r");
FILE *FileBatTemp = fopen(FilePathNameBat, "w");
if (!FileXmlTemp || !FileBatTemp)
{
m_LastErrCode = 2;
m_LastErrMes = ERR_MES_2;
return false;
}
char FileStr[256] = { 0 };
while (fgets(FileStr, 256, FileXmlTemp))
{
fprintf(FileBatTemp, "%s", FileStr);
}
fclose(FileXmlTemp);
fclose(FileBatTemp);
if (!(m_pFileHandle = fopen(FilePathName, "w")))
{
m_LastErrCode = 2;
m_LastErrMes = ERR_MES_2;
return false;
}
delete[]m_pFileBuffur;
m_pFileBuffur = new char[m_FileSize + 1024];
memset(m_pFileBuffur, 0, m_FileSize + 1024);
NodeToBuffer(m_pRootNode, m_pFileBuffur, 0);
fwrite(m_pFileBuffur, 1, strlen(m_pFileBuffur), m_pFileHandle);
fclose(m_pFileHandle);
return true;
}
bool XmlFile::AnalysisFile()
{
int i = 0;
for (i; i < m_FileSize; i++)
{
if ('\n' == m_pFileBuffur[i] || '\t' == m_pFileBuffur[i])
{
m_pFileBuffur[i] = ' ';
}
}
if ('<' == m_pFileBuffur[0] && '?' == m_pFileBuffur[1])
{
for (i = 0; i < m_FileSize; i++)
{
if ('>' == m_pFileBuffur[i])
{
break;
}
}
}
XmlNode *pNode = new XmlNode;
AnalysisXml(pNode, m_pFileBuffur + i + 1, strlen(m_pFileBuffur + i + 1));
m_pRootNode = pNode->m_pChild;
m_pCurNode = m_pRootNode;
return true;
}
void XmlFile::LocateRoot()
{
m_pCurNode = m_pRootNode;
}
bool XmlFile::LocateNode(XmlNode *pNode)
{
if (!pNode)
{
m_LastErrCode = 1;
m_LastErrMes = ERR_MES_1;
return false;
}
m_pCurNode = pNode;
return true;
}
bool XmlFile::LocateParent()
{
if (!m_pCurNode)
{
m_LastErrCode = 3;
m_LastErrMes = ERR_MES_3;
return false;
}
m_pCurNode = m_pCurNode->m_pParent;
return true;
}
bool XmlFile::LocatePrev()
{
if (!m_pCurNode)
{
m_LastErrCode = 3;
m_LastErrMes = ERR_MES_3;
return false;
}
m_pCurNode = m_pCurNode->m_pPrev;
return true;
}
bool XmlFile::LocateNext()
{
if (!m_pCurNode)
{
m_LastErrCode = 3;
m_LastErrMes = ERR_MES_3;
return false;
}
m_pCurNode = m_pCurNode->m_pNext;
return true;
}
bool XmlFile::LocatepChild()
{
if (!m_pCurNode)
{
m_LastErrCode = 3;
m_LastErrMes = ERR_MES_3;
return false;
}
m_pCurNode = m_pCurNode->m_pChild;
return true;
}
XmlNode *XmlFile::GetCurNode()
{
return m_pCurNode;
}
std::string XmlFile::GetCurNodeName()
{
if (!m_pCurNode)
{
m_LastErrCode = 3;
m_LastErrMes = ERR_MES_3;
return "";
}
return m_pCurNode->m_Name;
}
std::string XmlFile::GetCurNodeValue()
{
if (!m_pCurNode)
{
m_LastErrCode = 3;
m_LastErrMes = ERR_MES_3;
return "";
}
return m_pCurNode->m_Value;
}
XmlAttribute *XmlFile::GetCurNodeAttribute()
{
if (!m_pCurNode)
{
m_LastErrCode = 3;
m_LastErrMes = ERR_MES_3;
return nullptr;
}
return m_pCurNode->m_pAttribute;
}
XmlNode *XmlFile::AddXmlNode(XmlNode *pParent, std::string Name, std::string Value)
{
if (!pParent || "" == Name)
{
m_LastErrCode = 1;
m_LastErrMes = ERR_MES_1;
return nullptr;
}
XmlNode *pXmlNodeTemp = new XmlNode;
pXmlNodeTemp->m_Name = Name;
pXmlNodeTemp->m_Value = Value;
pXmlNodeTemp->m_pParent = pParent;
if (!pParent->m_pChild)
{
pParent->m_pChild = pXmlNodeTemp;
}
else
{
XmlNode *pPrev = pParent->m_pChild;
while (pPrev->m_pNext)
{
pPrev = pPrev->m_pNext;
}
pPrev->m_pNext = pXmlNodeTemp;
pXmlNodeTemp->m_pPrev = pPrev;
}
return pXmlNodeTemp;
}
bool XmlFile::UpdateXmlNode(XmlNode *pNode, std::string Name, std::string Value)
{
if (!pNode || "" == Name)
{
m_LastErrCode = 1;
m_LastErrMes = ERR_MES_1;
return false;
}
pNode->m_Name = Name;
pNode->m_Value = Value;
return true;
}
void XmlFile::DeleteXmlNode(XmlNode *pNode)
{
DeleteNode(pNode);
}
bool XmlFile::AddNodeAttribute(XmlNode *pNode, std::string Name, std::string Value)
{
if (!pNode || "" == Name || "" == Value)
{
m_LastErrCode = 1;
m_LastErrMes = ERR_MES_1;
return false;
}
XmlAttribute *pTemp = new XmlAttribute;
pTemp->m_Name = Name;
pTemp->m_Value = Value;
if (!pNode->m_pAttribute)
{
pNode->m_pAttribute = pTemp;
}
else
{
XmlAttribute *pPrev = pNode->m_pAttribute;
while (pPrev->m_pNext)
{
pPrev = pPrev->m_pNext;
}
pPrev->m_pNext = pTemp;
}
return true;
}
bool XmlFile::UpdateNodeAttribute(XmlNode *pNode, std::string Name, std::string Value)
{
XmlAttribute *pTemp = nullptr;
pTemp = pNode->m_pAttribute;
while (pTemp)
{
if (Name == pTemp->m_Name)
{
pTemp->m_Value = Value;
return true;
}
}
m_LastErrCode = 3;
m_LastErrMes = ERR_MES_3;
return false;
}
void XmlFile::DeleteNodeAttribute(XmlNode *pNode)
{
DeleteAttribute(pNode->m_pAttribute);
}
void XmlFile::DeleteNodeAttribute(XmlNode *pNode, std::string Name)
{
XmlAttribute *pPrev = pNode->m_pAttribute;
XmlAttribute *pTemp = nullptr;
if (pPrev&&Name == pPrev->m_Name)
{
pNode->m_pAttribute = pNode->m_pAttribute->m_pNext;
delete pPrev;
return;
}
pTemp = pPrev->m_pNext;
while (pTemp)
{
if (Name == pTemp->m_Name)
{
pPrev->m_pNext = pTemp->m_pNext;
delete pTemp;
return;
}
pPrev = pPrev->m_pNext;
pTemp = pTemp->m_pNext;
}
}
void AnalysisXml(XmlNode *pParent, char *Buffer, long BufferSize)
{
if (!pParent)
{
return;
}
int i = 0;
int flag = 1;
char *NodeBuffer = new char[1024];
memset(NodeBuffer, 0, 1024);
char BeginName[32] = { 0 };
char EndName[32] = { 0 };
char *NextBuf = nullptr;
XmlNode *pNodeTemp = nullptr;
for (i; i < BufferSize; i++)
{
while (Buffer[i])
{
if ('<' == Buffer[i] && '/' != Buffer[i + 1] && '!' != Buffer[i + 1])
{
int j = 0;
while ('>' != Buffer[i])
{
NodeBuffer[j] = Buffer[i + 1];
j++;
i++;
}
NextBuf = &Buffer[i + 1];
strncpy(BeginName, NodeBuffer, 32);
for (int i = 0; i < strlen(BeginName); i++)
{
if (' ' == BeginName[i] || '=' == BeginName[i] || '>' == BeginName[i])
{
BeginName[i] = 0;
}
}
break;
}
i++;
}
while (Buffer[i])
{
if ('<' == Buffer[i] && '/' == Buffer[i + 1])
{
int j = 0;
i += 2;
while ('>' != Buffer[i])
{
EndName[j] = Buffer[i];
j++;
i++;
}
EndName[j] = 0;
if (!strcmp(BeginName, EndName))
{
pNodeTemp = new XmlNode;
pNodeTemp->m_Name = std::string(BeginName);
pNodeTemp->m_pParent = pParent;
if (!pParent->m_pChild)
{
pParent->m_pChild = pNodeTemp;
}
else
{
XmlNode *pPrev = pParent->m_pChild;
while (pPrev->m_pNext)
{
pPrev = pPrev->m_pNext;
}
pPrev->m_pNext = pNodeTemp;
pNodeTemp->m_pPrev = pPrev;
}
char *pChr = strchr(NextBuf, '<');
if (pChr != NextBuf)
{
char Value[256] = { 0 };
strcpy(Value, std::string(NextBuf, pChr).data());
Trim(Value);
pNodeTemp->m_Value = Value;
}
CreateNode(pNodeTemp, NodeBuffer);
if (0 == flag)
{
AnalysisXml(pNodeTemp, NextBuf, strlen(NextBuf));
}
else if (1 == flag)
{
AnalysisXml(pParent, NextBuf, strlen(NextBuf));
}
delete[]NodeBuffer;
return;
}
else
{
flag = 0;
}
}
i++;
}
}
}
void CreateNode(XmlNode *pNode, char *pValue)
{
XmlAttribute *pAttributeTemp = nullptr;
XmlAttribute *pPrev = nullptr;
char NameValue[32] = { 0 };
char *pChr = nullptr;
pChr = strchr(pValue, ' ');
if (!pChr)
{
return;
}
pValue = pChr + 1;
int Len = strlen(pChr);
while (true)
{
if (!(pChr = strchr(pValue, '=')))
{
return;
}
pAttributeTemp = new XmlAttribute;
if (!pNode->m_pAttribute)
{
pNode->m_pAttribute = pAttributeTemp;
}
else
{
pPrev = pNode->m_pAttribute;
while (pPrev->m_pNext)
{
pPrev = pPrev->m_pNext;
}
pPrev->m_pNext = pAttributeTemp;
}
strcpy(NameValue, std::string(pValue, pChr).data());
Trim(NameValue);
pAttributeTemp->m_Name = NameValue;
pValue = pChr + 1;
if (!(pChr = strchr(pValue, '"')))
{
return;
}
pValue = pChr + 1;
if (!(pChr = strchr(pValue, '"')))
{
return;
}
strcpy(NameValue, std::string(pValue, pChr).data());
Trim(NameValue);
pAttributeTemp->m_Value = NameValue;
pValue = pChr + 1;
}
}
void Trim(char*Buffer)
{
int i = 0;
int len = strlen(Buffer);
for (i = len - 1; i >= 0; i--)
{
if (' ' != Buffer[i] && '\t' != Buffer[i] && '"' != Buffer[i] && '"' != Buffer[i] && '\n' != Buffer[i])
{
break;
}
Buffer[i] = 0;
}
for (i = 0; i < len; i++)
{
if (' ' != Buffer[i] && '\t' != Buffer[i] && '"' != Buffer[i] && '"' != Buffer[i] && '\n' != Buffer[i])
{
break;
}
}
if (0 != i)
{
strncpy(Buffer, Buffer + i, len - i);
Buffer[len - i] = 0;
}
}
void NodeToBuffer(XmlNode *pNode, char *pBuffer, int Depth)
{
if (!pNode)
{
return;
}
for (int i = 0; i < Depth; i++)
{
strcat(pBuffer, "\t");
}
strcat(pBuffer, "<");
strcat(pBuffer, pNode->m_Name.data());
XmlAttribute *pAtt = pNode->m_pAttribute;
while (pAtt)
{
strcat(pBuffer, " ");
strcat(pBuffer, pAtt->m_Name.data());
strcat(pBuffer, "=\"");
strcat(pBuffer, pAtt->m_Value.data());
strcat(pBuffer, "\"");
pAtt = pAtt->m_pNext;
}
strcat(pBuffer, ">");
strcat(pBuffer, pNode->m_Value.data());
if (pNode->m_pChild)
{
strcat(pBuffer, "\n");
NodeToBuffer(pNode->m_pChild, pBuffer, Depth + 1);
for (int i = 0; i < Depth; i++)
{
strcat(pBuffer, "\t");
}
strcat(pBuffer, "</");
strcat(pBuffer, pNode->m_Name.data());
strcat(pBuffer, ">\n");
}
else if (pNode->m_pNext)
{
strcat(pBuffer, "</");
strcat(pBuffer, pNode->m_Name.data());
strcat(pBuffer, ">\n");
NodeToBuffer(pNode->m_pNext, pBuffer, Depth);
}
else
{
strcat(pBuffer, "</");
strcat(pBuffer, pNode->m_Name.data());
strcat(pBuffer, ">\n");
}
return;
}
void DeleteNode(XmlNode *pNode)
{
if (!pNode)
{
return;
}
DeleteNode(pNode->m_pChild);
DeleteNode(pNode->m_pNext);
DeleteAttribute(pNode->m_pAttribute);
pNode->m_pParent = nullptr;
pNode->m_pPrev = nullptr;
pNode->m_pNext = nullptr;
pNode->m_pChild = nullptr;
pNode->m_pAttribute = nullptr;
delete pNode;
}
void DeleteAttribute(XmlAttribute *pAttribute)
{
if (!pAttribute)
{
return;
}
DeleteAttribute(pAttribute->m_pNext);
delete pAttribute;
pAttribute = nullptr;
}
文章以及源码均为原创,当然欢迎转载,转载请加说明
|