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

📄 xml.cpp

📁 相当不错的入门程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:

// 得到节点的第一个属性
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 + -