📄 cutil-xml.c
字号:
#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 + -