解析XML

[cpp] view plaincopyprint?精短高效的XML解析器,纯C单一程序,应用于银行的国税库行横向联网接口系统中,稳定可靠,运行速度飞快,非相应的JAVA程序可比.以下为大部分源码: 
/* Copyright (c) 2005 wzs   */ 
#include <stdlib.h>  
#include <stdio.h>  
#include <string.h>  
#include <time.h>  
#include <varargs.h>  
#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<p2; p++); 
      if (*(p2-1)=='/') {   /* 处理空标记<abc/> */ 
       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,"<?xml version=", 14)!=0) 
    { 
     XPrtErr("无XML内容头!"); 
     return -1; 
   } 
    p=strstr(xmlbuf, "?>") ; 
    if (p==NULL) 
    { 
     XPrtErr("XML内容头无结尾!"); 
     return -1; 
   } 
    p1=DelSpace(p+2); 
    for (p=p1, maxnn=1; p<pend ; p++) { 
     if (*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 (k<maxnn   ) 
     { 
     vtype0 = vtype ; 
      vtype = XmlReadNodeVal( xTree, &xstr); 
      if ( vtype <= XVAL_NONE) {   break;   } 
      switch (vtype) { 
       case XVAL_NOTE : 
         vtype = vtype0 ; 
         break; 
       case XVAL_NBEGIN : 
       if ( XAddSubNode( xTree , &xstr ) == NULL) k=maxnn+1 ;    
          break ; 
       case XVAL_NEND : 
       XRetParentNode( xTree ) ;       /* 返回父节点:    */ 
       break; 
     case XVAL_DATA : 
       XElementData( xTree , &xstr ) ; /*   修改当前节点元素值: */ 
       break; 
     default : 
        if (vtype>10)   break;   /* printf(" ===c增加%d/n",   vtype -10 ); */ 
      } 
     } 
   *xmlbuf = '/0';    /* 置已解析标志   */   
   maxnn = xTree->curNode->index ;    /* 最终当前节点号 */    
for (k=0; k<xTree->nodeCount ; 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; k<xTree->nodeCount ; 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, "<?xml version=/"1.0/" encoding=/"%s/"?>/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, "</%s>/n/0", Tag); 
    return (xmlbuf + strlen(Tag)+4 ); 
   } else { 
    for (k=0; k < (*Tag - '0'); k ++) *(xmlbuf + k)='/t'; 
    sprintf(xmlbuf+k, "</%s>/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</%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</%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</%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</%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, "<!--%s-->/n/0", note ); 
   return (xmlbuf + strlen(note)+8 ); 
/*   写任意串写缓冲 */ 
char * XWriteBuf (char *buf, char *str) 
   sprintf(buf, "%s/0", str ); 
   return (buf + strlen(str) ); 

你可能感兴趣的:(解析XML)