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

📄 cutil-xml.c

📁 Linux环境下常用功能的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "cutil.h"

#define MAX_ELEMENT_ATTR_NUM 32

typedef struct _CutilXmlAttr  CutilXmlAttr;

struct _CutilXmlAttr {
	char *pszAttrName;
	char *pszAttrValue;
};


struct _CutilXml {
	char *pszElementName;
	char *pszElementValue;
	int nAttrNum;
	CutilXmlAttr struAttr[MAX_ELEMENT_ATTR_NUM];
	CutilXml *pstruNext;
	CutilXml *pstruFirstChild;
	CutilXml *pstruParent;
};

/**
 * cutil_xml_new:
 * @pszRootName:ROOT的名称.
 * @pszRootValue:ROOT的值.
 *
 * 创建一个新的XML报文.TODO在意外的时候释放内存
 *
 * Returns: 成功返回建立的XML树,失败返回NULL
 */
CutilXml *cutil_xml_new(const char *pszRootName, const char *pszRootValue)
{
	CutilXml *pstruXml;

	pstruXml = (CutilXml *)calloc(1, sizeof(CutilXml));
	pstruXml -> pstruNext = NULL;
	pstruXml -> pstruFirstChild = NULL;
	pstruXml -> pstruParent = NULL;
	pstruXml -> nAttrNum = 0;

	if(pszRootName)
		pstruXml -> pszElementName = strdup(pszRootName);
	else
		pstruXml -> pszElementName = NULL;

	if(pszRootValue && pszRootName)
		pstruXml -> pszElementValue = strdup(pszRootValue);
	else
		pstruXml -> pszElementValue = NULL;

	return pstruXml;
}

static CutilXml * in_get_next_node(const char *pszXmlBuffer, char **pszNodeStart, char **pszNodeEnd)
{
	CutilXml *pstruXml;
	char *pszStart, *pszEnd, *pszAttr;
	int nLen;

	if(pszXmlBuffer == NULL)
		return NULL;

	pszStart = strchr(pszXmlBuffer, '<');
	if(pszStart == NULL)
		return NULL;
	*pszNodeStart = pszStart;

	if(memcmp(pszStart, "<?", 2) == 0)
	{
		/*
		 * 处理指令
		 */
		pszStart = strstr(pszStart + 2, "?>");
		if(pszStart == NULL)
			return NULL;

		pszStart = strchr(pszStart + 2, '<');
		if(pszStart == NULL)
			return NULL;		
	}
	if(memcmp(pszStart, "<!--", 4) == 0)
	{
		/*
		 * 注释
		 */
		pszStart = strstr(pszStart + 4, "-->");
		if(pszStart == NULL)
			return NULL;

		pszStart = strchr(pszStart + 2, '<');
		if(pszStart == NULL)
			return NULL;		
	}

	pszStart ++;
	pszEnd = strchr(pszStart, '>');
	if(pszEnd == NULL)
		return NULL;
	*pszNodeEnd =  pszEnd + 1;

	pstruXml = (CutilXml *)calloc(1, sizeof(CutilXml));
	pstruXml -> pszElementName = NULL;
	pstruXml -> pszElementValue = NULL;
	pstruXml -> nAttrNum = 0;
	pstruXml -> pstruNext = NULL;
	pstruXml -> pstruFirstChild = NULL;
	pstruXml -> pstruParent = NULL;

	pszAttr = strchr(pszStart, ' ');
	if((pszAttr == NULL) || (pszAttr > pszEnd))
		pszAttr = pszEnd;

	nLen = pszAttr - pszStart;
	pstruXml -> pszElementName = (char *)calloc(1, nLen + 1);
	memcpy(pstruXml -> pszElementName, pszStart, nLen);
	cutil_string_trim_space(pstruXml -> pszElementName);

	if(pstruXml -> pszElementName[0] == '/')
		return pstruXml;

	while(pszAttr < pszEnd)
	{
		pszStart = pszAttr;
		pszAttr = strstr(pszStart, "=\"");
		if(pszAttr == NULL)
			break;
		
		/*
		 * 属性名称
		 */
		nLen = pszAttr - pszStart;
		pstruXml -> struAttr[pstruXml -> nAttrNum].pszAttrName = (char *)calloc(1, nLen + 1);
		memcpy(pstruXml -> struAttr[pstruXml -> nAttrNum].pszAttrName, pszStart, nLen);
		cutil_string_trim_space(pstruXml -> struAttr[pstruXml -> nAttrNum].pszAttrName);

		/*
		 * 属性值
		 */
		pszStart = pszAttr + 2;
		pszAttr = strchr(pszStart, '"');
		if(pszAttr == NULL)
			break;
		nLen = pszAttr - pszStart;
		pstruXml -> struAttr[pstruXml -> nAttrNum].pszAttrValue = (char *)calloc(1, nLen + 1);
		memcpy(pstruXml -> struAttr[pstruXml -> nAttrNum].pszAttrValue, pszStart, nLen);
		cutil_string_trim_space(pstruXml -> struAttr[pstruXml -> nAttrNum].pszAttrValue);
		
		pstruXml -> nAttrNum ++;
		if(pstruXml -> nAttrNum >= MAX_ELEMENT_ATTR_NUM)
			break;
		pszAttr ++;
	}
	return pstruXml;
}

static char * in_import_node(CutilXml *pstruParent, const char *pszXmlBuffer)
{
	CutilXml *pstruXml, *pstruNextXml;
	char *pszNodeStart, *pszNodeEnd;
	int nLen;

	pstruXml = pstruParent;
	pszNodeEnd = (char *)pszXmlBuffer;
	while(TRUE)
	{
		pszXmlBuffer = pszNodeEnd;
		pstruNextXml = in_get_next_node(pszXmlBuffer, &pszNodeStart, &pszNodeEnd);
		if(pstruNextXml == NULL)
			return NULL;
		nLen = pszNodeStart - pszXmlBuffer;
		if((pstruParent -> pszElementValue == NULL) && (nLen > 0) )
		{
			/*
			 * 获取节点的值
			 */
			pstruParent -> pszElementValue = (char *)calloc(1, nLen + 1);
			memcpy(pstruParent -> pszElementValue, pszXmlBuffer, nLen);
			cutil_string_trim_space(pstruParent -> pszElementValue);
		}
		if(pstruNextXml -> pszElementName[0] == '/')
		{
			free(pstruNextXml -> pszElementName);
			free(pstruNextXml);
			return pszNodeEnd;
		}
		else
		{
			if(pstruParent -> pstruFirstChild == NULL)
			{
				pstruParent -> pstruFirstChild = pstruNextXml;
			}
			else
			{
				pstruXml = pstruParent -> pstruFirstChild;
				while(pstruXml -> pstruNext)
					pstruXml = pstruXml -> pstruNext;
				pstruXml -> pstruNext = pstruNextXml;
			}
			pszNodeEnd = in_import_node(pstruNextXml, pszNodeEnd);
		}
	}
}

/**
 * cutil_xml_import:
 * @pszXmlBuffer:包含XML数据的报文.
 *
 * 导入报文到XML结构
 *
 * Returns: 成功返回建立的XML树,失败返回NULL
 */
CutilXml * cutil_xml_import(const char *pszXmlBuffer)
{
	CutilXml *pstruXml;
	char *pszNodeStart, *pszNodeEnd;

	pstruXml = in_get_next_node(pszXmlBuffer, &pszNodeStart, &pszNodeEnd);
	if(pstruXml == NULL)
		return NULL;

	in_import_node(pstruXml, pszNodeEnd);
	return pstruXml;
}

/**
 * cutil_xml_import_from_file:
 * @pszXmlFile:包含XML数据的文件名称.
 *
 * 导入文件内容到XML结构
 *
 * Returns: 成功返回建立的XML树,失败返回NULL
 */
CutilXml *cutil_xml_import_from_file(const char *pszXmlFile)
{
	FILE *pstruFile;
	int nSize;
	char *pszBuffer;
	CutilXml *pstruXml;

	nSize = cutil_file_get_size(pszXmlFile);
	if(nSize <= 0)
		return NULL;

	pstruFile = fopen(pszXmlFile, "r");
	if(pstruFile == NULL)
	{
		cutil_log_error(N_("open xml file %s error %s\n"), pszXmlFile, strerror(errno));
		return NULL;
	}
	pszBuffer = (char *)calloc(1, nSize + 1);
	fread(pszBuffer, nSize, 1, pstruFile);
	fclose(pstruFile);

	pstruXml = cutil_xml_import(pszBuffer);
	free(pszBuffer);

	return pstruXml;
}

static int in_xml_export(CutilXml *pstruXml, char *pszBuffer, int nMaxSize, int nLevel)
{
	int i, nLen;
	char *pszStart = pszBuffer;
	if(pstruXml == NULL)
		return 0;

	nMaxSize -= nLevel;
	if(nMaxSize <= 0)
		return -1;
	for(i = 0 ; i < nLevel ; i ++)
		strcat(pszStart, "\t");
	pszStart += i;

	nMaxSize -= 1;
	if(nMaxSize <= 0)
		return -1;
	strcat(pszStart, "<");
	pszStart ++;

	nLen = strlen(pstruXml -> pszElementName);
	nMaxSize -= nLen;
	if(nMaxSize <= 0)
		return -1;
	strcat(pszStart, pstruXml -> pszElementName);
	pszStart += nLen;

	for(i = 0 ; i < pstruXml -> nAttrNum; i ++)
	{
		nLen = strlen(pstruXml->struAttr[i].pszAttrName) + strlen(pstruXml->struAttr[i].pszAttrValue) + 6;
		nMaxSize -= nLen;
		if(nMaxSize <= 0)
			return -1;
		strcat(pszStart, " ");
		strcat(pszStart , pstruXml->struAttr[i].pszAttrName);
		strcat(pszStart, " = \"");
		strcat(pszStart , pstruXml->struAttr[i].pszAttrValue);
		strcat(pszStart, "\"");		
		pszStart += nLen;
	}
	nMaxSize -= 1;
	if(nMaxSize <= 0)
		return -1;
	strcat(pszStart, ">");
	pszStart ++;

	if(pstruXml -> pszElementValue)
	{
		nLen = strlen(pstruXml -> pszElementValue);
		nMaxSize -= nLen;
		if(nMaxSize <= 0)
			return -1;
		strcat(pszStart, pstruXml -> pszElementValue);
		pszStart += nLen;
	}


	if(pstruXml -> pstruFirstChild)
	{
		nMaxSize -= 1;
		if(nMaxSize <= 0)
			return -1;
		strcat(pszStart, "\n");
		pszStart ++;

		in_xml_export(pstruXml -> pstruFirstChild, pszStart, nMaxSize, nLevel + 1);

		nMaxSize -= 1;
		if(nMaxSize <= 0)
			return -1;
		strcat(pszStart, "\n");
		pszStart ++;

		nMaxSize -= nLevel;
		if(nMaxSize <= 0)
			return -1;
		for(i = 0 ; i < nLevel ; i ++)
			strcat(pszStart, "\t");
		pszStart += i;
	}

	nMaxSize -= 2;
	if(nMaxSize <= 0)
		return -1;
	strcat(pszStart, "</");

	nLen = strlen(pstruXml -> pszElementName);
	nMaxSize -= nLen;
	if(nMaxSize <= 0)
		return -1;
	strcat(pszStart, pstruXml -> pszElementName);
	pszStart += nLen;

	nMaxSize -= 1;
	if(nMaxSize <= 0)
		return -1;
	strcat(pszStart, ">");

	if(pstruXml -> pstruNext)
	{
		nMaxSize -= 1;
		if(nMaxSize <= 0)
			return -1;
		strcat(pszStart, "\n");
		pszStart ++;
		in_xml_export(pstruXml -> pstruNext, pszStart, nMaxSize, nLevel);
	}
	return 0;
}

/**
 * cutil_xml_export:
 * @pstruXml:包含数据的XML树.
 * @pszBuffer: 存放数据的缓存
 * @nMaxSize :数据的最大空间
 *
 * 导出数据到报文
 *
 * Returns: 成功返回0,失败返回-1
 */
int cutil_xml_export(CutilXml *pstruXml, char *pszBuffer, int nMaxSize)
{
	return in_xml_export(pstruXml, pszBuffer, nMaxSize, 0);
}

static int in_xml_export_file(CutilXml * pstruXml, FILE *pstruFile, int nLevel)
{
	int i;

	if(pstruXml == NULL)
		return 0;
	for(i = 0 ; i < nLevel ; i ++)
		fprintf(pstruFile, "\t");
	fprintf(pstruFile, "<%s", pstruXml -> pszElementName);
	for(i = 0 ; i < pstruXml -> nAttrNum; i ++)
		fprintf(pstruFile, " %s = \"%s\"", pstruXml->struAttr[i].pszAttrName, pstruXml->struAttr[i].pszAttrValue);
	if(pstruXml -> pszElementValue)
		fprintf(pstruFile, ">%s", pstruXml -> pszElementValue);
	else
		fprintf(pstruFile, ">");
	if(pstruXml -> pstruFirstChild)
	{
		fprintf(pstruFile, "\n");
		in_xml_export_file(pstruXml -> pstruFirstChild, pstruFile, nLevel + 1);
		fprintf(pstruFile, "\n");
		for(i = 0 ; i < nLevel ; i ++)
			fprintf(pstruFile, "\t");
	}
	fprintf(pstruFile, "</%s>", pstruXml -> pszElementName);
	if(pstruXml -> pstruNext)
	{
		fprintf(pstruFile, "\n");
		in_xml_export_file(pstruXml -> pstruNext, pstruFile, nLevel);
	}
	return 0;
}

/**
 * cutil_xml_export_to_file:
 * @pstruXml:包含数据的XML树.
 * @pszXmlFile:保存数据的文件,如果为NULL则输出到stderr
 *
 * 导出数据到报文
 *
 * Returns: 成功返回0,失败返回-1
 */
int cutil_xml_export_to_file(CutilXml *pstruXml, const char *pszXmlFile)
{
	FILE *pstruFile;

	if(pszXmlFile == NULL)
	{

⌨️ 快捷键说明

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