分享
 
 
 

编程手记之ANSI C篇-(五)XMLDOC

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

编程手记之ANSI C篇-(五)XMLDOC

文档技术发展至今,Lotus Notes, MS Office, Adobe PDF, WPS 等,无不红极一时,各霸一方,但谁又能执其牛耳呢?如果说传统的文档是数据加样式的二合体的话,那么样式是牢笼,他将数据紧紧地束缚于其中,甲方乙方样式各自表征,死不相往来,在企业的数据海洋中垒起一个个信息孤岛,客户只是这些孤岛中的一个茫然的游客。但XML文档之横空出世仿佛改变了一切,成为当前业界最振奋人心之亮点。XML文档最朴实之处在于他首先关注的是数据,并将之描述成规范的表达,数据成为XML文档中的灵魂,至于样式,他通过外部的XML模式引入,这样客户占据了数据上的主动,并且拥有自由选择何种模式来表征数据的权利,岂不快哉!如果你对XML心仪,那么就赶快进入XML世界吧!

对于程序员来说,还是走离幻想的天空,踏踏实实地来写一段程序吧!前面已经实现了XML解析自动机,今天将在此基础上完成XML文档的访问接口-DOM。

DOM的结构实际上是一个二叉分析树的结构,DOM的节点由解析自动机在分析XML文档的过程中被逐一创建,XML文档分析请见《编程手记之ANSI C篇-(四)XML解析自动机》,以下来看一看DOM的接口功能实现:

/*用于格式化DOM节点属性时的缓冲结构*/

typedef struct _ProperBuf{

TCHAR* pBuf;

int size;

int max;

}ProperBuf;

/************************************************************

function: 创建DOM

return: DOM的连接件指针

*************************************************************/

LINKPTR XML_AllocDom(void)

{

/*使用二叉分析树作为DOM*/

return CreateTreeData();

}

/************************************************************

function: 销毁DOM

dom: DOM的连接件指针

*************************************************************/

void XML_FreeDom(LINKPTR dom)

{

DestroyTreeData(dom);

}

/************************************************************

functoin: 分析XML文档,生成DOM树

dom: DOM的连接件指针

szXML: XML文档字符串

return: 零值分析成功,非零值失败

*************************************************************/

int XML_Parse(LINKPTR dom,TCHAR* szXML)

{

XMLMac mac;

mac.token = szXML;

mac.act = paChild;

mac.parent = NULL;

mac.tree = dom;

/*自动机推演*/

_XMLParseTagEntity(&mac);

return mac.retcode;

}

/************************************************************

function: 取得DOM节点的子节点计数

ptrNode: 节点的连接件指针

return: 子节点的计数

*************************************************************/

int XML_ChildNodeCount(LINKPTR ptrNode)

{

return GetTreeDataChildItemCount(ptrNode);

}

/************************************************************

function: 取得DOM的根节点

ptrDom: DOM的连接件指针

return: 根节点的连接件指针,空树返回NULL

*************************************************************/

LINKPTR XML_GetRootNode(LINKPTR ptrDom)

{

return GetTreeDataRootItem(ptrDom);

}

/************************************************************

function: 取得第一个子节点

ptrNode: 节点的连接件指针

return: 子节点的连接件指针,没有子节点则返回NULL

*************************************************************/

LINKPTR XML_GetChildNode(LINKPTR ptrNode)

{

return GetTreeDataChildItem(ptrNode);

}

/************************************************************

function: 取得父节点

ptrNode: 节点的连接件指针

return: 父节点的连接件指针,根节点没有父节点,返回NULL

*************************************************************/

LINKPTR XML_GetParentNode(LINKPTR ptrNode)

{

return GetTreeDataParentItem(ptrNode);

}

/************************************************************

function: 取得后一个兄弟节点

ptrNode: 节点的连接件指针

return: 兄弟节点的连接件指针,没有后继节点则返回NULL

*************************************************************/

LINKPTR XML_GetNextSiblingNode(LINKPTR ptrNode)

{

return GetTreeDataNextSiblingItem(ptrNode);

}

/************************************************************

function: 取得前一个兄弟节点

ptrNode: 节点的连接件指针

return: 兄弟节点的连接件指针,没有前趋节点则返回NULL

*************************************************************/

LINKPTR XML_GetPrevSiblingNode(LINKPTR ptrNode)

{

return GetTreeDataPrevSiblingItem(ptrNode);

}

/************************************************************

function: 由节点连接件指针回溯DOM连接件指针

ptrNode: 节点的连接件指针

return: DOM的连接件指针

*************************************************************/

LINKPTR XML_DomFromNode(LINKPTR ptrNode)

{

return GetTreeDataFromItem(ptrNode);

}

/************************************************************

function: 取得节点的名称

ptrNode: 节点的连接件指针

szName: 字符缓冲区

max: 缓冲区大小

return: 实际拷贝的字符数

*************************************************************/

int XML_GetNodeName(LINKPTR ptrNode,TCHAR* szName,int max)

{

return ReadTreeDataItemProper(ptrNode,NODENAME,szName,max);

}

/************************************************************

function: 取得节点名称的字符串指针

ptrNode: 节点的连接件指针

return: 字符串指针

*************************************************************/

TCHAR* XML_GetNodeNamePtr(LINKPTR ptrNode)

{

return GetTreeDataItemProperPtr(ptrNode,NODENAME);

}

/************************************************************

function: 设置节点名称

ptrNode: 节点的连接件指针

szName: 名称字符串

*************************************************************/

void XML_SetNodeName(LINKPTR ptrNode,const TCHAR* szName)

{

WriteTreeDataItemProper(ptrNode,NODENAME,-1,(TCHAR*)szName,-1);

}

/************************************************************

functoin: 取得节点的文本字符串长度

ptrNode: 节点的连接件指针

return: 字符串长度值

*************************************************************/

int XML_GetNodeTextLength(LINKPTR ptrNode)

{

return GetTreeDataItemProperLength(ptrNode,NODETEXT);

}

/************************************************************

function: 取得节点的文本

ptrNode: 节点的连接件指针

szText: 字符串缓冲区

max: 缓冲区大小

return: 实际拷贝的字符数

*************************************************************/

int XML_GetNodeText(LINKPTR ptrNode,TCHAR* szText,int max)

{

return ReadTreeDataItemProper(ptrNode,NODETEXT,szText,max);

}

/************************************************************

function: 设置节点的文本

ptrNode: 节点的连接件指针

szText: 文本字符串

*************************************************************/

void XML_SetNodeText(LINKPTR ptrNode,const TCHAR* szText)

{

WriteTreeDataItemProper(ptrNode,NODETEXT,-1,(TCHAR*)szText,-1);

}

/************************************************************

function: 取得节点文本的字符串指针

ptrNode: 节点的连接件指针

return: 字符串指针

*************************************************************/

TCHAR* XML_GetNodeTextPtr(LINKPTR ptrNode)

{

return GetTreeDataItemProperPtr(ptrNode,NODETEXT);

}

/************************************************************

function: 取得节点属性值字符串指针

ptrNode: 节点的连接件指针

szKey: 属性名称

return: 属性值字符串指针

*************************************************************/

TCHAR* XML_GetNodeAttrPtr(LINKPTR ptrNode,const TCHAR* szKey)

{

return GetTreeDataItemProperPtr(ptrNode,szKey);

}

/************************************************************

function: 取得节点属性值字符串长度

ptrNode: 取得节点属性值字符串指针

szKey: 属性名称

return: 属性值字符串长度

*************************************************************/

int XML_GetNodeAttrLength(LINKPTR ptrNode,const TCHAR* szKey)

{

return GetTreeDataItemProperLength(ptrNode,szKey);

}

/************************************************************

function: 取得节点属性值字符串

ptrNode: 节点连接件指针

szKey: 属性名称

szVal: 字符串缓冲区

max: 缓冲区大小

return: 实际拷贝的字符数

*************************************************************/

int XML_GetNodeAttr(LINKPTR ptrNode,const TCHAR* szKey,TCHAR* szVal,int max)

{

return ReadTreeDataItemProper(ptrNode,szKey,szVal,max);

}

/************************************************************

function: 设置节点的属性值

ptrNode: 节点连接件指针

szKey: 属性名称

szVal: 属性值

*************************************************************/

void XML_SetNodeAttr(LINKPTR ptrNode,const TCHAR* szKey,const TCHAR* szVal)

{

WriteTreeDataItemProper(ptrNode,(TCHAR*)szKey,-1,(TCHAR*)szVal,-1);

}

/************************************************************

function: 插入一个新节点到DOM

ptrDom: DOM连接件指针

ptrNode: 父节点连接件指针

return: 新节点的连接件指针,如果父节点为NULL,则返回的新节点为根节点

*************************************************************/

LINKPTR XML_InsertNode(LINKPTR ptrDom,LINKPTR ptrNode)

{

LINKPTR node;

node = InsertTreeDataItem(ptrDom,ptrNode,LINK_LAST);

XML_SetNodeName(node,_T("NewNode"));

return node;

}

/************************************************************

function: 从DOM中删除一个节点

ptrDom: DOM连接件指针

ptrNode: 待删除的节点的连接件指针

*************************************************************/

void XML_DeleteNode(LINKPTR ptrDom,LINKPTR ptrNode)

{

DeleteTreeDataItem(ptrDom,ptrNode);

}

/************************************************************

function: 删除DOM中的所有节点

ptrDom: DOM连接件指针

*************************************************************/

void XML_DeleteAllNodes(LINKPTR ptrDom)

{

ClearTreeData(ptrDom);

}

/************************************************************

function: 回调函数,用于格式化节点的属性串

szName: 属性名称

namelen: 属性名称长度

szValue: 属性值

vallen: 属性值长度

param: 回调函数的回传参数,在此是一个ProperBuf的结构的指针

return: 零值格式化成功,非零值则出错

*************************************************************/

static int XML_FormatNodeProper(const TCHAR* szName,int namelen,const TCHAR* szValue,int vallen,void* param)

{

int len;

ProperBuf* pbi = (ProperBuf*)param;

/*skip NODENAME and NODETEXT*/

if(!_tcscmp(szName,NODENAME))

return 0;

else if(!_tcscmp(szName,NODETEXT))

return 0;

/*calc this property token length*/

len = namelen + vallen + _tcslen(_T("='' "));

if(pbi->size + len > pbi->max) /*buffer is overflow*/

{

return -1;

}

/*add property token to buffer end*/

if(pbi->pBuf != NULL)

_stprintf(pbi->pBuf + pbi->size,_T("%s=%c%s%c "),((szName)? szName : _T("")),_T('"'),((szValue)? szValue : _T("")),_T('"'));

pbi->size += len;

return 0;

}

/************************************************************

function: 格式化节点

ptrNode: 节点的连接件指针

pbi: 数据缓冲结构指针

return: 当前格式化入数据缓冲区的字节数

*************************************************************/

int XML_FormatNode(LINKPTR ptrNode,ProperBuf* pbi)

{

TCHAR* szName = NULL;

TCHAR* szText = NULL;

int len;

if(ptrNode == NULL)

return pbi->size;

while(ptrNode)

{

len = GetTreeDataItemProperLength(ptrNode,NODENAME);

if(pbi->size + len + (int)_tcslen(_T("< ")) > pbi->max)

return -1;

/*格式化节点首部*/

if(pbi->pBuf)

{

szName = (TCHAR*)calloc(len + 1,sizeof(TCHAR));

ReadTreeDataItemProper(ptrNode,NODENAME,szName,len);

_stprintf(pbi->pBuf + pbi->size,_T("<%s "),szName);

}

len = len + _tcslen(_T("< "));

pbi->size += len;

/*枚举节点的属性集合并格式化*/

if(EnumHashEntity(GetTreeDataItemHashTable(ptrNode),(EnumHashEntityPtr)XML_FormatNodeProper,(void*)pbi))

return -1;

len = GetTreeDataItemProperLength(ptrNode,NODETEXT);

if(pbi->size + len + (int)_tcslen(_T(">")) > pbi->max)

return -1;

/*格式化节点的文本节*/

if(pbi->pBuf)

{

szText = (TCHAR*)calloc(len + 1,sizeof(TCHAR));

ReadTreeDataItemProper(ptrNode,NODETEXT,szText,len);

_stprintf(pbi->pBuf + pbi->size,_T(">%s"),szText);

free(szText);

}

len = len + _tcslen(_T(">"));

pbi->size += len;

/*格式花子节点*/

if(XML_FormatNode(GetTreeDataChildItem(ptrNode),pbi) == -1)

return -1;

len = GetTreeDataItemProperLength(ptrNode,NODENAME) + _tcslen(_T("</>\r\n"));

if(pbi->size + len > pbi->max)

return -1;

/*格式化节点的尾部*/

if(pbi->pBuf)

{

_stprintf(pbi->pBuf + pbi->size,_T("</%s>\r\n"),szName);

free(szName);

}

pbi->size += len;

ptrNode = GetTreeDataNextSiblingItem(ptrNode);

}

return pbi->size;

}

/************************************************************

function: 格式化DOM树

ptrDom: DOM连接件指针

pBuf: 数据缓冲区

max: 缓冲区大小

return: 实际格式化的字节数,-1则出错

*************************************************************/

int XML_Format(LINKPTR ptrDom,TCHAR* pBuf,int max)

{

ProperBuf bi;

LINKPTR ptrNode = GetTreeDataRootItem(ptrDom);

bi.max = max;

bi.pBuf = pBuf;

bi.size = 0;

return XML_FormatNode(ptrNode,&bi);

}

/************************************************************

function: 取得格式化DOM的数据缓冲区的大小

ptrDom: DOM连接件指针

reutrn: 所需的缓冲区大小,-1则出错

*************************************************************/

int XML_FormatSize(LINKPTR ptrDom)

{

return XML_Format(ptrDom,NULL,MAX_INT);

}

/************************************************************

function: 将DOM写入XML文件

ptrDom: DOM连接件指针

szFile: 文件名称

xmlencode: 编码类型

return: 零值成功,非零值失败

*************************************************************/

int XML_WriteFile(LINKPTR ptrDom,const TCHAR* szFile,const TCHAR* xmlencode)

{

int len,tag;

TCHAR* pBuf;

FILE* file ;

TCHAR szXML[100];

file = _tfopen(szFile,_T("wt"));

if(file == NULL)

return DOM_FAIL;

if(xmlencode == NULL)

_stprintf(szXML,_T("<?xml version=%c1.0%c encoding=%cutf-8%c ?>\r\n"),_T('"'),_T('"'),_T('"'),_T('"'));

else

_stprintf(szXML,_T("<?xml version=%c1.0%c encoding=%c%s%c ?>\r\n"),_T('"'),_T('"'),_T('"'),xmlencode,_T('"'));

len = _tcslen(szXML);

if(len != (int)fwrite(szXML,sizeof(TCHAR),len,file))

{

fclose(file);

return DOM_FAIL;

}

len = XML_FormatSize(ptrDom);

if(len < 0)

{

fclose(file);

return DOM_FAIL;

}

pBuf = (TCHAR*)calloc(len + 1,sizeof(TCHAR));

tag = XML_Format(ptrDom,pBuf,len);

if(tag < 0 )

{

free(pBuf);

fclose(file);

return DOM_FAIL;

}

if(len != (int)fwrite(pBuf,sizeof(TCHAR),len,file))

{

free(pBuf);

fclose(file);

return DOM_FAIL;

}else

{

free(pBuf);

fclose(file);

return DOM_SUCCEED;

}

}

/************************************************************

function: 从XML文件中生成DOM树

ptrDom: DOM连接件指针

szFile: 文件名称

return: 零值成功,非零值失败

*************************************************************/

int XML_ReadFile(LINKPTR ptrDom,const TCHAR* szFile)

{

int len = 0;

void* pBuf;

FILE* file;

file = _tfopen(szFile,_T("r"));

if(file == NULL)

return DOM_FAIL;

while(_fgettc(file) != EOF)

len ++;

fseek(file,0,SEEK_SET);

pBuf = calloc(len + 1,sizeof(TCHAR));

if(len != (int)fread(pBuf,sizeof(TCHAR),len,file))

{

fclose(file);

free(pBuf);

return DOM_FAIL;

}

fclose(file);

XML_DeleteAllNodes(ptrDom);

if(XP_SUCCESS != XML_Parse(ptrDom,(TCHAR*)pBuf))

{

free(pBuf);

return DOM_FAIL;

}else

{

free(pBuf);

return DOM_SUCCEED;

}

}

有关连接件、二叉树请参见《编程手记之ANSI C篇-(一)通用连接件》,《编程手记之ANSI C篇-(三)二叉分析树》,谨以这些天来的一些叽叽歪歪之陈述,慕求志同道合之战友,与君共勉!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有