纯C语言XML解析器

精短高效的XML解析器,纯C单一程序,应用于银行的国税库行横向联网接口系统中,稳定可靠,运行速度飞快,非相应的JAVA程序可比.以下为大部分源码: /* Copyright (c) 2005 wzs */ #include #include #include #include #include #include "xmlparse.h" /*xml得到节点名值, 返回: 1节点标识名开头, 2节点标识名结尾, 3 注释 , 4元素数据 <=0有错误 */ #define XVAL_NBEGIN 1 #define XVAL_NEND 2 #define XVAL_NOTE 3 #define XVAL_DATA 4 #define XVAL_TAG 5 /* 空标志 */ #define XVAL_NONE 0 #define XVAL_ERROR -1 static int isSpace(int c) /* 是空否 */ { switch (c) { case 0x20: case 0xD: case 0xA: case 0x9: return 1; } return 0; } static int isNameTChar(int c) /* 有效的名称前导符 */ { return (c>='A' && c<='Z') || (c>='a' && c<='z') || (c=='_') ; } int EqXString (XSTRING *dxs, XSTRING *sxs ) /* X字串赋值 */ { dxs->text = sxs->text ; dxs->len = sxs->len ; return 0; } int EqXNode (XNODE *dx, XNODE *sx ) /* X节点赋值 */ { EqXString ( &(dx->name), &(sx->name) ); dx->index = sx->index ; dx->parentNode = sx->parentNode ; dx->level = sx->level ; dx->tagCount = sx->tagCount ; EqXString ( &(dx->data), &(sx->data) ); return 0; } /* 增加同级节点: */ XNODE *XAddNode(XTREE *xTree , XSTRING *name) { if (xTree->curNode->parentNode == NULL || xTree->nodeCount >= xTree->nodeMaxCount ) return NULL ; (xTree->nodeCount) ++ ; xTree->preNode = xTree->curNode ; xTree->curNode = & (xTree->nodeList[ xTree->nodeCount -1 ] ) ; xTree->curNode->index = xTree->nodeCount -1 ; EqXString (&(xTree->curNode->name), name); xTree->curNode->parentNode = xTree->preNode->parentNode ; xTree->curNode->level = xTree->preNode->level ; (xTree->curNode->parentNode->tagCount) ++ ; return (xTree->curNode); } /* 增加子节点: */ XNODE *XAddSubNode(XTREE *xTree , XSTRING *name) { if (xTree->curNode == NULL || xTree->nodeCount >= xTree->nodeMaxCount ) return NULL ; (xTree->nodeCount) ++ ; xTree->preNode = xTree->curNode ; xTree->curNode = & (xTree->nodeList[ xTree->nodeCount -1 ]) ; xTree->curNode->index = xTree->nodeCount -1 ; EqXString (&(xTree->curNode->name), name); xTree->curNode->parentNode = xTree->preNode ; xTree->curNode->level = xTree->preNode->level +1 ; (xTree->preNode->tagCount) ++ ; return (xTree->curNode); } /* 返回父节点: */ XNODE *XRetParentNode(XTREE *xTree ) { if (xTree->curNode->parentNode == NULL ) return NULL; xTree->preNode = xTree->curNode ; xTree->curNode = xTree->curNode->parentNode ; return (xTree->curNode); } /* 修改当前节点元素值: */ int XElementData(XTREE *xTree , XSTRING *data) { if (xTree->curNode == NULL ) return -1 ; /* if (xTree->curNode->tagCount>0) return -2; */ EqXString ( &(xTree->curNode->data), data) ; return 0; } char * DelSpace( char *xbuf) /* 删除前导空 */ { char *p ; for (p=xbuf ; isSpace(*p) ; p++); /* 去掉空字符 */ return (p); } int XmlAttr( XTREE *xTree, XSTRING *val) /* 处理属性: 当作叶节点, 子节点数为-1, 返回增加的属性节点数 */ { XSTRING xn, xv; int k=0; char *p1, *p, *p2; p=DelSpace(val->text); while (p && *p) { p1= p ; p2=strchr(p1, '='); if (p2==NULL) break ; xn.text = p1 ; *p2='/0'; xn.len = p2- p1 ; p=DelSpace(p2+1); if (*p !='"') break ; p1= p ; p2=strchr(p1+1, '"'); if (p2==NULL) break ; xv.text = p1+1; *p2 ='/0'; xv.len = p2-p1-1; /* 增加属性值节点 */ if (XAddSubNode(xTree, &xn)==NULL) break ; k++; if (XElementData(xTree , &xv) <0 ) break ; xTree->curNode->tagCount = -1; XRetParentNode( xTree ) ; p=DelSpace(p2+1); } return (k); } /* xml得到节点名值, 返回: 1节点标识名开头, 2节点标识名结尾, 3 注释 , 4元素数据 0无 -1有错误 */ int XmlReadNodeVal(XTREE *xTree, XSTRING *val ) { char *p ,*p1, *p2; int ivtype=XVAL_NONE ; p=xTree->xBufPos ; p=DelSpace( xTree->xBufPos) ; /* 删除前导空 */ if (*p !='<') { /* 数据 */ p1 = p; p2=strchr(p1, '<'); val->text = p1; val->len = ( p2 ? p2-p1 : 0); ivtype = ( p2 && p2 < xTree->xBufEnd ? XVAL_DATA : XVAL_NONE) ; xTree->xBufPos = (p2 ? p2 : xTree->xBufEnd); goto OKExit33qqq ; } /* 前导为< */ p++; if ( *p=='/' ) { /* 标记尾 */ p1 = p+1; p2=strchr(p1, '>'); if (p2==NULL) { /* 错误 */ goto ErrExit33qqq ; } else { ivtype=XVAL_NEND; val->text = p1; val->len = p2-p1; xTree->xBufPos = p2 +1 ; } } else if (isNameTChar(*p)) { /* 标记头 */ p1=p; p2=strchr(p1,'>'); if (p2==NULL) { /* 错误 */ goto ErrExit33qqq ; } for (p=p1; *p!=' ' && p */ ivtype=11; val->text = p1; if (p>=p2) p=p2-1; val->len = p - p1; if ( XAddSubNode( xTree , val ) == NULL) goto ErrExit33qqq ; if (p < p2-1 ) /* 增加属性节点 */ { *(p2-1) ='/0'; p++; val->text = p ; val->len = p2-1- p; ivtype += XmlAttr(xTree, val ); } XRetParentNode( xTree ) ; } else { ivtype=XVAL_NBEGIN; val->text = p1; val->len = p - p1; if (p < p2) /* 增加属性节点 */ { if ( XAddSubNode( xTree , val ) == NULL) goto ErrExit33qqq ; *(p2) ='/0'; p++; val->text = p ; val->len = p2 - p; ivtype = 11+ XmlAttr(xTree, val ); } } xTree->xBufPos = p2 +1 ; } else if (*p=='!') { if (*(p+1)=='-' && *(p+2)=='-') /* 注释 */ { p+=3; p1=DelSpace(p); p2=strstr(p1, "-->"); /*注释尾 */ if (p2==NULL) { /* 错误 */ goto ErrExit33qqq ; } else { ivtype=XVAL_NOTE; xTree->xBufPos = p2+3; val->text = p1; val->len = (p2 - p1) / sizeof(char) ; } goto OKExit33qqq ; } } OKExit33qqq: return (ivtype) ; ErrExit33qqq : ivtype=XVAL_ERROR; xTree->xBufPos = xTree->xBufEnd ; return (ivtype) ; } /* 读xml并解析到X树 */ int XmlParseRead(char *xmlbuf, int xmlsize, XTREE *xTree) { char *p, *p1, *pend = xmlbuf + xmlsize; XSTRING xstr ; XNODE *xn ; register int k; int maxnn=0, vtype=XVAL_NONE, vtype0=XVAL_NONE ; memset( xTree, 0x00, sizeof(XTREE) ); if (memcmp(xmlbuf,"") ; if (p==NULL) { XPrtErr("XML内容头无结尾!"); return -1; } p1=DelSpace(p+2); for (p=p1, maxnn=1; p' || *p=='"') maxnn++; if (*p=='>') if (*(p-1) == '/') maxnn++; /* 空标记 */ } maxnn = maxnn / 2 + 2 ; xTree->xBuf =xmlbuf; xTree->xBufEnd = xmlbuf + xmlsize ; xTree->xBufPos = p1 ; for (k=0; k<99; k++) { vtype = XmlReadNodeVal( xTree, &xstr); if (vtype==XVAL_NBEGIN) break; else if (vtype!=XVAL_NOTE) break ; } xTree->nodeCount = 0; if (vtype!=XVAL_NBEGIN) { xTree->nodeMaxCount = 0; XPrtDebug("空XML内容"); return 0; } XPrtDebug("===申请节点存储空间=%d ", maxnn); xTree->nodeList = (XNODE *) calloc( maxnn , sizeof(XNODE) ); /* 申请节点存储空间 */ if (xTree->nodeList == NULL ) { XPrtErr("申请节点存储空间(%d)失败!", maxnn ); return -2; } xTree->nodeMaxCount = maxnn ; memset( xTree->nodeList , 0x00, maxnn * sizeof(XNODE) ); xTree->rootNode = &(xTree->nodeList[0]); /* 根节点 */ xTree->rootNode->parentNode = NULL ; xTree->rootNode->index = xTree->rootNode->level =0; *(xstr.text+xstr.len)='/0'; EqXString (&(xTree->rootNode->name), &xstr); xTree->curNode = xTree->rootNode ; xTree->nodeCount=1; k=0; while (k10) break; /* printf(" ===c增加%d/n", vtype -10 ); */ } } *xmlbuf = '/0'; /* 置已解析标志 */ maxnn = xTree->curNode->index ; /* 最终当前节点号 */ for (k=0; knodeCount ; k++){ xn =&( xTree->nodeList[k] ); if (xn->name.text) *(xn->name.text + xn->name.len) ='/0'; else xn->name.text=xmlbuf ; if (xn->data.text) *(xn->data.text + xn->data.len) ='/0'; else xn->data.text=xmlbuf ; } XPrtDebug ( " 节点数=%d/n", xTree->nodeCount); if (maxnn) XPrtErr("XML文件不完整(%d) ", maxnn ); xTree->curNode= xTree->rootNode ; return (maxnn); } int XmlParseFree( XTREE *xTree ) { if (xTree->nodeMaxCount>0) free(xTree->nodeList); xTree->nodeMaxCount=xTree->nodeCount = 0; return 0; } int printXtree(XTREE *xTree) { int k ; XNODE *xn ; XPrtDebug(" ******** xTree 结构, 总节点数=%d, 节点空间=%d ******** ", xTree->nodeCount, xTree->nodeMaxCount); XPrtDebug("/t节点号 父节点 节点级 子节数 节点名 节点数据"); for (k=0; knodeCount ; k++){ xn =&( xTree->nodeList[k] ); XPrtDebug("/t%d %d %d %d [%s] [%s]",xn->index,(xn->parentNode ? xn->parentNode->index : -1), xn->level, xn->tagCount,xn->name.text, xn->data.text ); } XPrtDebug("*****************************************************************"); return 0; } /* 从当前节点往下取得节点: */ XNODE *XmlGetNodeByName (XTREE *xTree, char *nodename) { register int k; XNODE *xn ; for (k=xTree->curNode->index+1 ; k< xTree->nodeCount ; k++) { xn =&( xTree->nodeList[k] ); if (memcmp(xn->name.text, nodename, xn->name.len )==0 ) break; } if (k>= xTree->nodeCount) return NULL ; xTree->curNode = xn ; return ( xn ) ; } /* 从当前节点往下取得子节点(根据父节点名和节点名): */ XNODE *XmlGetNode (XTREE *xTree, char *pname, char *nodename) { register int k; XNODE *xn ; for (k=xTree->curNode->index+1 ; k< xTree->nodeCount ; k++) { xn =&( xTree->nodeList[k] ); if (memcmp(xn->name.text, nodename, xn->name.len )==0 && memcmp(xn->parentNode->name.text, pname, xn->parentNode->name.len)==0 ) break; } if (k>= xTree->nodeCount) return NULL ; xTree->curNode = xn ; return ( xTree->curNode ) ; } /* 从当前节点往下取得子节点(根据父节点和节点名): */ XNODE *XmlGetChildNode (XTREE *xTree, XNODE *pnode, char *nodename) { register int k; XNODE *xn ; for (k=xTree->curNode->index+1 ; k< xTree->nodeCount ; k++) { xn =&( xTree->nodeList[k] ); if (xn->level <= pnode->level ) return NULL ; if (xn->parentNode == pnode && memcmp(xn->name.text, nodename, xn->name.len )==0) break; } if (k>= xTree->nodeCount) return NULL ; xTree->curNode = xn ; return ( xTree->curNode ) ; } /* 取得叶节点: */ XNODE *XmlGetTag (XTREE *xTree, XNODE *pnode, char *tagname) { register int k; XNODE *xn ; if (pnode == NULL) return NULL ; for (k = pnode->index+1 ; k< xTree->nodeCount ; k++) { xn =&( xTree->nodeList[k] ); if (xn->level <= pnode->level ) return NULL ; if (xn->parentNode == pnode && memcmp(xn->name.text, tagname, xn->name.len )==0) break; } if (k>= xTree->nodeCount) return NULL ; xTree->curNode = xn ; return ( xTree->curNode ) ; } /* 代码编码转换1: */ int XEnCode(XSTRING *xs, char *scode, char *dcode ) { int k, lens=strlen(scode), lend=strlen(dcode), nrr=0; char *tmpbuf, *p,*p0, *pt, *pend ; if (strstr(xs->text, scode)==NULL) return 0; pend=xs->text + xs->len ; k=lend - lens ; if (k<0) k=0; tmpbuf = (char *) malloc( xs->len + k * 100 + 1 ); if (tmpbuf==NULL) return -1; memset(tmpbuf, 0x00, xs->len + k * 100 ); for (p0=p=xs->text, pt=tmpbuf; p && nrr<100 ; nrr++) { p=strstr(p0, scode); if (p==NULL || p>pend ) { memcpy(pt, p0, pend - p0); pt += pend - p0 ; break; } memcpy(pt, p0, p-p0); pt +=p-p0; memcpy(pt, dcode, lend); pt += lend ; p0=p+lens ; } pt='/0'; lens=strlen(tmpbuf) ; memcpy(xs->text, tmpbuf, lens ); xs->len = lens ; *(xs->text + lens)='/0'; free(tmpbuf); return (nrr); } /* XML代码符号转换: */ int XmlDataEnCode(XSTRING *xs ) { XEnCode(xs, "<", "<"); XEnCode(xs, ">", ">"); XEnCode(xs, """, "/""); XEnCode(xs, "'", "'"); XEnCode(xs, "&", "&"); /* 为防止包中分隔符与业务系统冲突,非标准转换 */ XEnCode(xs, "|", ":"); return (0); } /* XML代码符号反转换: */ int XmlDataUnCode(XSTRING *xs ) { XEnCode(xs, "&", "&"); XEnCode(xs, "<", "<"); XEnCode(xs, ">", ">"); XEnCode(xs, "/"", """); XEnCode(xs, "'", "'"); return (0); } /* 写xml头 */ char * XmlWriteHead(char *xmlbuf, char *encode) { sprintf(xmlbuf, "/n/0",encode); return (xmlbuf + strlen(xmlbuf) ); } /* 写标识头 */ char * XmlWriteNodeBeg(char *xmlbuf, char *Tag) { int k; if (*Tag>'9') { sprintf(xmlbuf, "<%s>/n/0", Tag); return (xmlbuf + strlen(Tag)+3 ); } else { for (k=0; k < (*Tag - '0'); k ++) *(xmlbuf + k)='/t'; sprintf(xmlbuf + k, "<%s>/n/0", Tag+1); return (xmlbuf + k+ strlen(Tag)+2 ); } } /* 写标识尾 */ char * XmlWriteNodeEnd(char *xmlbuf, char *Tag) { int k ; if (*Tag>'9') { sprintf(xmlbuf, "/n/0", Tag); return (xmlbuf + strlen(Tag)+4 ); } else { for (k=0; k < (*Tag - '0'); k ++) *(xmlbuf + k)='/t'; sprintf(xmlbuf+k, "/n/0", Tag+1); return (xmlbuf+k + strlen(Tag)+3 ); } } /* 写数据元素 */ char * XmlWriteTag(char *xmlbuf, char *Tag, char *data ) { int k ; if (*Tag>'9') { sprintf(xmlbuf, "/t/t<%s>%s/n/0", Tag, data, Tag); return (xmlbuf + strlen(Tag)*2 + 8 + strlen(data) ); } else { for (k=0; k < (*Tag - '0'); k ++) *(xmlbuf + k)='/t'; sprintf(xmlbuf+k, "<%s>%s/n/0", Tag+1, data, Tag+1); return (xmlbuf + k + strlen(Tag)*2 + 4 + strlen(data) ); } } /* 写扩展(需要符号转换)的数据元素 */ char * XmlWriteExTag(char *xmlbuf, char *Tag, char *data ) { XSTRING xs ; char xdata[512]; int len=strlen(data); int k ; xs.text =xdata ; /* xmlbuf + strlen(Tag) +2 ; */ xs.len = len ; memcpy( xs.text, data, len); XmlDataUnCode( &xs ); *(xs.text + xs.len) = '/0'; if (*Tag>'9') { sprintf(xmlbuf, "/t/t<%s>%s/n/0", Tag, xs.text, Tag); return (xmlbuf + strlen(Tag)*2 + 8 + xs.len ); } else { for (k=0; k < (*Tag - '0'); k ++) *(xmlbuf + k)='/t'; sprintf(xmlbuf + k, "<%s>%s/n/0", Tag+1, xs.text, Tag+1); return (xmlbuf + k + strlen(Tag)*2 + 4 + xs.len ); } } /* 写注释 */ char * XmlWriteNote (char *xmlbuf, char *note) { sprintf(xmlbuf, "/n/0", note ); return (xmlbuf + strlen(note)+8 ); } /* 写任意串写缓冲 */ char * XWriteBuf (char *buf, char *str) { sprintf(buf, "%s/0", str ); return (buf + strlen(str) ); }

 

你可能感兴趣的:(纯C语言XML解析器)