📄 xml.cpp
字号:
// 得到节点的第一个属性
LPXMLATTRIB CXML::GetFirstXmlAttrib(LPXMLNODE pParent)
{ if(pParent==NULL) return NULL;
return (LPXMLATTRIB)pParent->m_pAttrib;
}
// 得到节点的下一个属性
LPXMLATTRIB CXML::GetNextXmlAttrib(LPXMLATTRIB pAttrib)
{ if(pAttrib==NULL) return NULL;
return (LPXMLATTRIB)pAttrib->m_pNext;
}
// 设置属性值
BOOL CXML::SetXmlAttribValue(LPXMLNODE pNode,const char* pszName,const char* pszValue)
{ // 检查参数是否合法
if(pNode==NULL||pszName==NULL||pszValue==NULL) return FALSE;
// 查找属性名,如果查找不到则创建
LPXMLATTRIB pAttrib=FindXmlAttrib(pNode,pszName);
if(pAttrib==NULL)
{ pAttrib=AllocXmlAttribAtTail(pNode);
pAttrib->m_Name=AllocXmlStr(pszName,strlen(pszName));
}
FreeXmlStr(pAttrib->m_Value);
pAttrib->m_Value=AllocXmlStr(pszValue,strlen(pszValue));
return TRUE;
}
// 水印生成
/*BOOL CXML::GenerateWaterMark(const char* pszRoot,char* pszWaterMark,LONG nWaterMarkLen)
{
// 清除返回数据
if(pszWaterMark!=NULL&&nWaterMarkLen>0) memset(pszWaterMark,0,nWaterMarkLen);
// 查找节点,如果不存在,则返回失败
LPXMLNODE pXmlNode=FindXmlWithPath(pszRoot);
if(pXmlNode==NULL) return FALSE;
// 遍历当前节点和子节点获取指纹信息(注:这里只获取前32K的内容)
char* lpszBuffer=NULL;
long nBufferSize=0,nBufferUsed=0;
WaterMarkXmlNodeAndChilds(pXmlNode,&lpszBuffer,&nBufferSize,&nBufferUsed);
// 对其的整数的部分进行加密
CBlowfish Blowfish((LPBYTE)"42362n01ygswd12#%3d5",20);
Blowfish.Encrypt((LPBYTE)lpszBuffer,nBufferUsed/8*8);
// 对全部缓冲区取MD5
char szMd5String[33]={0};
MD5_Buffer((LPBYTE)lpszBuffer,nBufferUsed,szMd5String);
nstrcpy(pszWaterMark,szMd5String,nWaterMarkLen);
// 释放临时的缓冲区
TFREE(lpszBuffer);
return TRUE;
}
*/
BOOL CXML::ParsingXml(char* lpszXml,LONG nXmlLen)
{
// 对XML文件进行解析,XML的解析是不断查找以<>区分的字符端的格式的
LPXMLNODE pParentNode=NULL;
LPXMLNODE pPrevNode=NULL;
const char* lpParsing=lpszXml;
while(lpParsing<lpszXml+nXmlLen)
{ // 跳过连续的空格
while((*lpParsing)==' '||(*lpParsing)=='\t'||(*lpParsing)=='\r'||(*lpParsing)=='\n') lpParsing++;
// 如果已经到文件结尾
if((*lpParsing)=='\0') break;
// 如果是一个字段,则追加到父节点中
if((*lpParsing)!='<')
{ const char* pszValue=lpParsing;
const char* pszNextKey=pszValue;
while((*pszNextKey)!='\0'&&(*pszNextKey)!='<') pszNextKey++;
if((*pszNextKey)=='\0') return NULL;
if(pParentNode==NULL) return FALSE;
// 查找有效的尾部,因为头部已经忽略掉了空格,因此这里是一定存在有效数据的
const char* pszValueEnd=pszNextKey-1;
while((*pszValueEnd)==' '||(*pszValueEnd)=='\t'||(*pszValueEnd)=='\r'||(*pszValueEnd)=='\n')
pszValueEnd--;
pszValueEnd++;
// 这里并不将键值尾部清0,因为可能因为后面判断
LPXMLNODE pXmlNode=AllocXmlNode(pParentNode,pPrevNode);
// 设置信息
pXmlNode->m_Key=AllocXmlStr(pszValue,pszValueEnd-pszValue);
pXmlNode->m_dwFlag=XMLNODE_VALUE;
// 更改前一个节点
pPrevNode=pXmlNode;
// 下一个节点从当前节点下一个字符开始
lpParsing=pszNextKey;
continue;
}
// 这是一个关键字,需要判断类型
else
{ lpParsing++;
// 如果是关键字结束
if((*lpParsing)=='/')
{ lpParsing++;
// 查找关键字头部和尾部
const char* pszKey=lpParsing;
while((*pszKey)==' '||(*pszKey)=='\t'||(*pszKey)=='\r'||(*pszKey)=='\n')
pszKey++;
if((*pszKey)=='\0'||(*pszKey)=='>') return NULL;
const char* pszKeyTail=pszKey;
while((*pszKeyTail)!='\0'&&(*pszKeyTail)!='>') pszKeyTail++;
if((*pszKeyTail)=='\0') return NULL;
if(pParentNode==NULL) return FALSE;
// 查找有效的尾部,因为头部已经忽略掉了空格,因此这里是一定存在有效数据的
const char* pszKeyEnd=pszKeyTail-1;
while((*pszKeyEnd)==' '||(*pszKeyEnd)=='\t'||(*pszKeyEnd)=='\r'||(*pszKeyEnd)=='\n')
pszKeyEnd--;
pszKeyEnd++;
(*(char*)pszKeyEnd)='\0';
// 查找键的头部
if(stricmp(pParentNode->m_Key.m_pStr,pszKey)!=0) return FALSE;
// 退回到上级节点
if(pParentNode!=NULL)
{ pParentNode=(LPXMLNODE)pParentNode->m_pParent;
pPrevNode=NULL;
if(pParentNode!=NULL)
{ pPrevNode=(LPXMLNODE)pParentNode->m_pChild;
if(pPrevNode!=NULL)
{ while(pPrevNode->m_pNext!=NULL)
pPrevNode=(LPXMLNODE)pPrevNode->m_pNext;
}
}
}
// 下一个节点从当前节点下一个字符开始
lpParsing=pszKeyTail+1;
continue;
}
// 如果是一个关键字开始(可能是)
else
{ BOOL bSysKey=FALSE;
if((*lpParsing)=='?')
{ bSysKey=TRUE;
lpParsing++;
}
// 查找键名开始和尾部(如果不存在则返回失败)
const char* pszKey=FindXmlKeyOrAttribBegin(lpParsing);
if(pszKey==NULL) return FALSE;
const char* pszKeyEnd=FindXmlKeyOrAttribEnd(pszKey);
if(pszKeyEnd==NULL) return FALSE;
// 找到正确的节点,申请一个对象并进行处理
const char* pszRest=pszKeyEnd;
LPXMLNODE pXmlNode=AllocXmlNode(pParentNode,pPrevNode);
// 设置信息
pXmlNode->m_Key=AllocXmlStr(pszKey,pszKeyEnd-pszKey);
pXmlNode->m_dwFlag=0;
// 更改前一个节点到当前节点
pPrevNode=pXmlNode;
// 查找关键字后开始查找各参数项
LPXMLATTRIB pXmlPrevAttrib=NULL;
const char* pszAttribName=FindXmlKeyOrAttribBegin(pszRest);
while(pszAttribName!=NULL)
{ // 分离出当前键值
const char* pszAttribNameEnd=FindXmlKeyOrAttribEnd(pszAttribName);
if(pszAttribNameEnd==NULL) return FALSE;
const char* pszAttribEqual=FindXmlAttribEqual(pszAttribNameEnd);
if(pszAttribEqual==NULL) return FALSE;
BOOL bSingleComma=FALSE;
const char* pszAttribValue=FindXmlAttribValueBegin(pszAttribEqual+1,bSingleComma);
if(pszAttribValue==NULL) return FALSE;
const char* pszAttribValueEnd=FindXmlAttribValueEnd(pszAttribValue+1,bSingleComma);
if(pszAttribValueEnd==NULL) return FALSE;
pszRest=pszAttribValueEnd+1;
(*(char*)pszAttribNameEnd)='\0';
(*(char*)pszAttribValueEnd)='\0';
// 添加属性节点
LPXMLATTRIB pXmlAttrib=AllocXmlAttrib(pXmlNode,pXmlPrevAttrib);
pXmlPrevAttrib=pXmlAttrib;
// 设置信息
pXmlAttrib->m_Name=AllocXmlStr(pszAttribName,strlen(pszAttribName));
pXmlAttrib->m_Value=AllocXmlStr(pszAttribValue,strlen(pszAttribValue));
// 查找下一个参数
pszAttribName=FindXmlKeyOrAttribBegin(pszRest);
}
// 跳过连续的空格
while((*pszRest)==' '||(*pszRest)=='\t'||(*pszRest)=='\r'||(*pszRest)=='\n') pszRest++;
// 检查是否存在尾部并进一步判断键类型
// 系统字段
if(strncmp(pszRest,"?>",2)==0)
{ if(!bSysKey) return FALSE;
pszRest+=2;
lpParsing=pszRest;
// 字段必须在最后结束
(*(char*)pszKeyEnd)='\0';
// 设置系统字段标志
pXmlNode->m_dwFlag|=XMLNODE_SYSKEY;
}
// 不包含子节点的字段
else if(strncmp(pszRest,"/>",2)==0)
{ if(bSysKey) return FALSE;
pszRest+=2;
lpParsing=pszRest;
// 字段必须在最后结束
(*(char*)pszKeyEnd)='\0';
// 设置键类型
pXmlNode->m_dwFlag|=XMLNODE_ITEMKEY;
}
// 包含子节点的字段或者这是一个字段的关闭
else if((*pszRest)=='>')
{ if(bSysKey) return FALSE;
pszRest+=1;
lpParsing=pszRest;
// 字段必须在最后结束
(*(char*)pszKeyEnd)='\0';
// 依据当前字段的类型准备结束字段
pXmlNode->m_dwFlag|=XMLNODE_KEYSET;
// 包含子节点,更改父节点为当前节点,更改前一个节点为当前节点的最后一个子节点
pParentNode=pXmlNode;
pPrevNode=(LPXMLNODE)pXmlNode->m_pChild;
if(pPrevNode!=NULL)
{ while(pPrevNode->m_pNext!=NULL)
pPrevNode=(LPXMLNODE)pPrevNode->m_pNext;
}
}
else
{ return FALSE;
}
}
}
}
// 判断全文结束
if(pParentNode!=NULL) return FALSE;
return TRUE;
}
// 查找XML关键字/属性名的开始
const char* CXML::FindXmlKeyOrAttribBegin(const char* lpszXml)
{
// 跳过连续的空格
while((*lpszXml)==' '||(*lpszXml)=='\t'||(*lpszXml)=='\r'||(*lpszXml)=='\n') lpszXml++;
// 如果开始字符是禁止字符则返回失败
char szBreakChars[]=" \t\r\n<>/?=\"";
if((*lpszXml)=='\0'||strchr(szBreakChars,(*lpszXml))!=NULL) return NULL;
return lpszXml;
}
// 查找XML关键字/属性名的结束
const char* CXML::FindXmlKeyOrAttribEnd(const char* lpszXmlTokenBegin)
{
// 查找到非空白字符
const char* lpszXml=lpszXmlTokenBegin;
char szBreakChars[]=" \t\r\n<>/?=\"";
while((*lpszXml)!='\0'&&strchr(szBreakChars,(*lpszXml))==NULL) lpszXml++;
// 关键字不允许为空
if(lpszXml==lpszXmlTokenBegin) return NULL;
// 关键字被结束字,换行中断
if((*lpszXml)=='\0'||(*lpszXml)=='\r'||(*lpszXml)=='\n') return NULL;
return lpszXml;
}
// 查找XML属性赋值操作
const char* CXML::FindXmlAttribEqual(const char* lpszXml)
{
// 跳过连续的空格
while((*lpszXml)==' '||(*lpszXml)=='\t'||(*lpszXml)=='\r'||(*lpszXml)=='\n') lpszXml++;
// 必须是等于号
if((*lpszXml)!='=') return NULL;
return lpszXml;
}
// 查找XML属性的开始
const char* CXML::FindXmlAttribValueBegin(const char* lpszXml,BOOL& bSingleComma)
{
// 跳过连续的空格
while((*lpszXml)==' '||(*lpszXml)=='\t'||(*lpszXml)=='\r'||(*lpszXml)=='\n') lpszXml++;
// 必须是等于引号
if((*lpszXml)!='"'&&(*lpszXml)!='\'') return NULL;
bSingleComma=((*lpszXml)!='"');
return lpszXml+1;
}
// 查找XML属性的结束
const char* CXML::FindXmlAttribValueEnd(const char* lpszXmlAttribValue,BOOL bSingleComma)
{
if(bSingleComma)
return strchr(lpszXmlAttribValue,'\'');
else return strchr(lpszXmlAttribValue,'"');
}
// 可用空间表分配和释放
XMLSTR CXML::AllocXmlStr(const char* pszStr,LONG nSize)
{ if(pszStr==NULL||nSize<=0) nSize=0;
XMLSTR XmlStr=AllocXmlStr(nSize+1);
if(pszStr!=NULL&&nSize>0) memcpy(XmlStr.m_pStr,pszStr,nSize);
XmlStr.m_pStr[nSize]='\0';
return XmlStr;
}
XMLSTR CXML::AllocXmlStr(LONG nSize)
{ XMLSTR XmlStr={0};
if(nSize>sizeof(XMLSMALLSTR))
{ XmlStr.m_bSmallStr=FALSE;
XmlStr.m_pStr=TMALLOC(nSize,CHAR);
}
else
{ XmlStr.m_bSmallStr=TRUE;
XmlStr.m_pStr=(LPSTR)m_heapXmlSmallStrs.AllocUnit();
}
return XmlStr;
}
LPXMLNODE CXML::AllocXmlNodeAtTail(LPXMLNODE pParentNode)
{ // 查找最后一个节点
LPXMLNODE pPrevNode=NULL;
if(pParentNode!=NULL)
{ pPrevNode=(LPXMLNODE)pParentNode->m_pChild;
while(pPrevNode!=NULL&&pPrevNode->m_pNext!=NULL)
pPrevNode=(LPXMLNODE)pPrevNode->m_pNext;
}
else
{ pPrevNode=m_pNodeLinks;
while(pPrevNode!=NULL&&pPrevNode->m_pNext!=NULL)
pPrevNode=(LPXMLNODE)pPrevNode->m_pNext;
}
// 在当前父节点下以及指定节点后创建新节点
return AllocXmlNode(pParentNode,pPrevNode);
}
LPXMLATTRIB CXML::AllocXmlAttribAtTail(LPXMLNODE pParentNode)
{ // 查找最后一个属性
LPXMLATTRIB pPrevAttrib=(LPXMLATTRIB)pParentNode->m_pAttrib;
while(pPrevAttrib!=NULL&&pPrevAttrib->m_pNext!=NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -