#include "xmlparse.h"
#define ISIGNORECH(buff) \ (buff[0] == ' ' || \ buff[0] == '\n' || \ buff[0] == '\r' || \ buff[0] == '\t' )
#define IGNORECH(buff) \ do \ { \ while( ISIGNORECH(buff) ) \ buff++; \ } while(0);
#define TRIM(a) do { \ char *p = (a) + strlen((a)) - 1; \ while( p > a && ISIGNORECH(p))p--; \ *++p = '\0'; \ p = (a);char *d = (a); \ while( *p != '\0' && ISIGNORECH(p))p++; \ while( *d != '\0')*d++ = *p++;} while(0);
#define CMP4(buff, c1, c2, c3, c4) \ ( ((unsigned char*)buff)[0] == c1 && ((unsigned char*)buff)[1] == c2 && \ ((unsigned char*)buff)[2] == c3 && ((unsigned char *)buff)[3] == c4 )
#define CMP5(buff, c1, c2, c3, c4, c5 ) \ ( CMP4(buff, c1, c2, c3, c4) && ((unsigned char *)buff)[4] == c5 )
#define CMP6(buff, c1, c2, c3, c4, c5, c6) \ ( CMP5(buff, c1, c2, c3, c4, c5) && ((unsigned char *)buff)[5] == c6 )
#define CMP7(buff, c1, c2, c3, c4, c5, c6, c7) \ ( CMP6(buff, c1, c2, c3, c4, c5, c6) && ((unsigned char *)buff)[6] == c7 )
#define CMP8(buff, c1, c2, c3, c4, c5, c6, c7, c8) \ ( CMP7(buff, c1, c2, c3, c4, c5, c6, c7) && ((unsigned char *)buff)[7] == c8 )
#define SKIP(val) pCtxt->cur += (val) #define NXT(val) pCtxt->cur[(val)] #define SCOPY(d, s) memcpy((d), (s), sizeof((d)) )
local void xmlSetError( const char *str) { char buff[32] = {0}; SCOPY(buff, str); buff[31] = '\0';
if( str[0] == '\0' ) fprintf(stderr, "error in the sting end !\n "); else fprintf(stderr, "error in [%s] \n", buff ); }
local BOOL xmlGetAttr( xmlCtxtPtr pCtxt, char *pbuf ) { if( *pCtxt->cur == '=' ) { SKIP(1); IGNORECH(pCtxt->cur);
if( *pCtxt->cur != '\"' ) return FALSE;
SKIP(1); while( *pCtxt->cur != '\"' ) { *pbuf++ = *pCtxt->cur++; } SKIP(1); } return TRUE; }
local int xmlParseStartTag( xmlCtxtPtr pCtxt, xmlNodePtr pNode ) { if( NXT(0) != '<' ) { return -1; } SKIP(1); IGNORECH(pCtxt->cur);
char *p = pNode->name; while( NXT(0) != '>' && NXT(0) != '/' && NXT(0) != '\0' && !ISIGNORECH(pCtxt->cur) ) { *p++ = *pCtxt->cur++; }
IGNORECH(pCtxt->cur); if( NXT(0) == '/' && NXT(1) == '>') { SKIP(2); return 1; }
p = pNode->property.name; while( NXT(0) != '>' && NXT(0) != '\0' && NXT(0) != '=' && !ISIGNORECH(pCtxt->cur) ) { *p++ = *pCtxt->cur++; }
IGNORECH(pCtxt->cur); if( !xmlGetAttr(pCtxt, pNode->property.value) ) return -1; IGNORECH(pCtxt->cur); if( NXT(0) != '>' ) return -1;
SKIP(1); return 0; }
local BOOL xmlParseEndTag( xmlCtxtPtr pCtxt, xmlNodePtr pNode ) { if( NXT(0) != '<' || NXT(1) != '/') { return FALSE; } else { SKIP(2); IGNORECH(pCtxt->cur); char *p = pNode->name; char *d = pCtxt->cur; //for display the error!
while( *p != '\0' ) { if( *p++ != *d++ ) return FALSE; }
if( !ISIGNORECH(d) && *d != '>') return FALSE;
pCtxt->cur = d;
IGNORECH(pCtxt->cur); if( NXT(0) != '>') { return FALSE; }
SKIP(1); }
return TRUE; }
local BOOL xmlParseElement( xmlCtxtPtr pCtxt, xmlNodePtr pNode ) {
IGNORECH(pCtxt->cur); int ret = xmlParseStartTag(pCtxt, pNode); if( ret < 0 ) { return FALSE; } else if( ret == 0) { char *p = pNode->content; while( NXT(0) != '\0' && NXT(0) != '<' ) { *p++ = *pCtxt->cur++; } TRIM(pNode->content); IGNORECH(pCtxt->cur);
while( NXT(0) == '<' && NXT(1) != '/' ) // child node
{ xmlNodePtr pNewNode = (xmlNodePtr)malloc(sizeof(xmlNode)); if( pNewNode == NULL ) { fprintf(stderr, "there is not enough memory !\n "); return FALSE; } memset( pNewNode, 0, sizeof(xmlNode) ); if( !xmlParseElement( pCtxt, pNewNode ) ) return FALSE;
if( pNode->left == NULL ) pNode->left = pNewNode; else { xmlNodePtr pNode2 = pNode->left; while ( pNode2->right != NULL ) pNode2 = pNode2->right;
pNode2->right = pNewNode; } }
IGNORECH(pCtxt->cur); if( !xmlParseEndTag( pCtxt, pNode ) ) { return FALSE; } }
return TRUE; }
void xmlFreeNodeEx(xmlNodePtr cur) { if( cur != NULL ) { xmlFreeNodeEx(cur->left); xmlFreeNodeEx(cur->right);
free(cur); } }
/* --------------- parse xml string ----------------- */ /* -------- */ xmlDocPtr xmlParseDoc( const char *cur ) { xmlCtxt cTxt; xmlDocPtr pDoc = (xmlDocPtr)malloc(sizeof(xmlDoc)); if( pDoc == NULL ) { fprintf(stderr, "there is not enough memory !\n "); return NULL; } memset( pDoc, 0, sizeof(xmlDoc) ); memset( &cTxt, 0, sizeof(xmlCtxt) );
cTxt.ctxt = (char*)malloc(strlen(cur) + 1); if( cTxt.ctxt == NULL ) { free(pDoc); fprintf(stderr, "there is not enough memory !\n "); return NULL; }
cTxt.cur = cTxt.ctxt; strcpy( cTxt.ctxt, cur ); xmlCtxtPtr pCtxt = &cTxt;
IGNORECH(pCtxt->cur); if( *pCtxt->cur != '<') { fprintf(stderr, "this xml doc can't parse!\n"); free(pDoc); free(pCtxt->ctxt); return NULL; }
if( CMP5(pCtxt->cur, '<', '?', 'x', 'm', 'l') ) { SKIP(5); /* IGNORECH(pCtxt->cur);
if( CMP7(pCtxt->cur, 'v', 'e', 'r', 's', 'i', 'o', 'n') ) { SKIP(7); /* version */ IGNORECH(pCtxt->cur);
if( !xmlGetAttr(pCtxt, pDoc->vesion) ) { free(pDoc); free(pCtxt->ctxt); return NULL; } }
IGNORECH(pCtxt->cur); if( CMP8(pCtxt->cur, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g') ) { SKIP(8); IGNORECH(pCtxt->cur);
if( !xmlGetAttr(pCtxt, pDoc->encoding) ) { free(pDoc); free(pCtxt->ctxt); return NULL; } }
IGNORECH(pCtxt->cur); if( pCtxt->cur[0] != '?' || pCtxt->cur[1] != '>' ) { free(pDoc); xmlSetError(pCtxt->cur); free(pCtxt->ctxt); return NULL; } SKIP(2);
}
pDoc->head = (xmlNodePtr)malloc(sizeof(xmlNode) ); if( pDoc->head == NULL ) { free(pDoc); fprintf(stderr, "there is not enough memory !\n "); free(pCtxt->ctxt); return NULL; } memset( pDoc->head, 0, sizeof(xmlNode) );
if( !xmlParseElement( pCtxt, pDoc->head ) ) { xmlFreeNode(pDoc->head); free(pDoc); xmlSetError(pCtxt->cur); free(pCtxt->ctxt); return NULL; }
free(pCtxt->ctxt); return pDoc; }
local int xmlGetNodeCount( xmlNodePtr pNode ) { if( pNode == NULL ) return 0; else { int nl = xmlGetNodeCount( pNode->left ); int nr = xmlGetNodeCount( pNode->right );
return (nl + nr + 1); } }
local void xmlNodeDump( xmlNodePtr pNode, char **txt ) { char *pTxt = *txt; while( pNode != NULL ) { char *pTmp = NULL;
*pTxt++ = '<'; pTmp = pNode->name; while ( *pTmp != '\0' ) { *pTxt++ = *pTmp++; } if( pNode->property.name[0] != '\0' ) { *pTxt++ = ' '; pTmp = pNode->property.name; while( *pTmp != '\0' ) { *pTxt++ = *pTmp++; } *pTxt++ = '='; *pTxt++ = '\"'; pTmp = pNode->property.value; while( *pTmp != '\0' ) { *pTxt++ = *pTmp++; } *pTxt++ = '\"'; } if( pNode->left == NULL && pNode->content[0] == '\0' ) //no child node
{ *pTxt++ = '/'; *pTxt++ = '>'; } else { *pTxt++ = '>'; pTmp = pNode->content; while( *pTmp != '\0' ) { *pTxt++ = *pTmp++; } xmlNodeDump(pNode->left, &pTxt); *pTxt++ = '<'; *pTxt++ = '/'; pTmp = pNode->name; while ( *pTmp != '\0' ) { *pTxt++ = *pTmp++; } *pTxt++ = '>';
}
pNode = pNode->right; } *txt = pTxt; }
void xmlDocDump(xmlDocPtr pDoc, char **txt) {
if( pDoc == NULL ) return;
int nCount = xmlGetNodeCount( pDoc->head ); *txt = (char*)malloc(nCount * 320 ); if( *txt == NULL ) { fprintf(stderr, "there is not enough memory !\n "); return; } memset(*txt, 0, nCount * 320 ); char *pTxt = *txt; sprintf(pTxt, "\n", pDoc->vesion, pDoc->encoding );
pTxt += strlen(pTxt); xmlNodeDump( pDoc->head, &pTxt );
}
#define GETXPATHNEXTFIELD do { \ IGNORECH(pxPath); \ if(*pxPath != '/')break;pxPath++;char *pTmp = tmp; \ while( *pxPath != '/' && *pxPath != '\0')*pTmp++ = *pxPath++; \ *pTmp = '\0'; \ } while(0);
#define GETXPATHNODE do { \ char *p = tNode;char *pTmp = tmp;char *p2 = tValue; \ while( *pTmp != '\0' && *pTmp != '[')*p++ = *pTmp++; \ *p = '\0';p = tAttr; \ if( *pTmp == '[' && *++pTmp == '@' ){pTmp++; \ while(*pTmp != '\0' && *pTmp != ']' && *pTmp != '=') \ *p++ = *pTmp++; *p = '\0'; \ if( *pTmp == '='){pTmp++; IGNORECH(pTmp); \ if( *pTmp != '\"')return FALSE; pTmp++; \ while( *pTmp != '\"' && *pTmp != '\0')*p2++ = *pTmp++; \ if( *pTmp != '\"')return FALSE;pTmp++; IGNORECH(pTmp); \ if( *pTmp != ']')return FALSE; } \ }*p = '\0'; *p2 = '\0'; \ } while(0);
#define ISXPATHEQUAL(a, b) ((a)[0] == '\0' || strcmp((a), (b)) == 0)
xmlNodePtr xmlParseXpath(const char *xPath, xmlDocPtr pDoc) { if( pDoc == NULL || xPath == NULL ) return NULL;
const char *pxPath = xPath; char tmp[XML_MAX_XPATH_LEN] = {0}; char tNode[XML_MAX_NODE_LEN] , tAttr[XML_MAX_ATTR_LEN], tValue[XML_MAX_ATTR_LEN]; xmlNodePtr pNode = pDoc->head;
while( pNode != NULL ) { GETXPATHNEXTFIELD; GETXPATHNODE; if( strcmp(pNode->name, tNode ) == 0 && ISXPATHEQUAL(tAttr, pNode->property.name ) && ISXPATHEQUAL(tValue, pNode->property.value) ) { if( *pxPath == '\0' ) break; pNode = pNode->left; } else { pNode = pNode->right; } } return pNode; }
xmlNodePtr xmlNewNode(const char *name, const char *content, const char *propName, const char *propValue) { xmlNodePtr pNode = (xmlNodePtr)malloc(sizeof(xmlNode) ); if( pNode == NULL ) { fprintf(stderr, "there is not enough memory !\n "); return NULL; } memset( pNode, 0, sizeof(xmlNode) ); strcpy( pNode->name, name ); if( content != NULL ) strcpy( pNode->content, content ); if( propName != NULL ) { strcpy( pNode->property.name, propName ); if( propValue != NULL ) strcpy( pNode->property.value, propValue ); }
return pNode; }
BOOL xmlAddNode( const char *xPath, xmlDocPtr pDoc, xmlNodePtr pNewNode ) { if( pNewNode == NULL ) return FALSE;
xmlNodePtr pNode = xmlParseXpath(xPath, pDoc ); if( pNode == NULL) return FALSE;
if( pNode->left == NULL ) pNode->left = pNewNode; else { pNode = pNode->left; while( pNode->right != NULL ) pNode = pNode->right;
pNode->right = pNewNode; }
return TRUE; }
|