Chinaunix首页 | 论坛 | 博客
  • 博客访问: 21259
  • 博文数量: 6
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-17 12:53
文章分类

全部博文(6)

文章存档

2008年(6)

我的朋友
最近访客

分类: C/C++

2008-06-12 11:27:07

写的比较乱, 以后整理一下;xmlparse.h:

#ifndef __XMLPARSER_H__
#define __XMLPARSER_H__

//#include


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef unsigned char BOOL;

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

#ifndef local
#define local    static
#endif

#define XML_MAX_NODE_LEN    64
#define    XML_MAX_ATTR_LEN    XML_MAX_NODE_LEN
#define XML_MAX_XPATH_LEN    XML_MAX_NODE_LEN + XML_MAX_ATTR_LEN + XML_MAX_ATTR_LEN + 32

/***************************************************************************
*
*    NOTE:     xml节点仅包含一个属性,且节点名,节点值,属性名,属性值最大长度固定
*
*
*
***************************************************************************/


typedef enum{
    XML_FIELD_HEAD = 0,
    XML_FIELD_NONE = 1,
    XML_FIELD_TAIL = 2,
    XML_FIELD_FAIL = 3
}xmlFieldType;


#pragma pack(1)

/*    ---------    xml attribute    -------------    */
typedef    struct    _xmlAttr xmlAttr;
typedef xmlAttr    *xmlAttrPtr;

typedef struct _xmlNode xmlNode;
typedef xmlNode *xmlNodePtr;

typedef struct _xmlDoc xmlDoc;
typedef xmlDoc *xmlDocPtr;

typedef struct _xmlCtxt xmlCtxt;
typedef xmlCtxt *xmlCtxtPtr;


struct _xmlAttr
{
    char name[XML_MAX_ATTR_LEN];
    char value[XML_MAX_ATTR_LEN];
};



struct _xmlNode
{
    /*name content attributes*/
    char name[XML_MAX_NODE_LEN];
    char content[XML_MAX_NODE_LEN];
    struct _xmlAttr property;

    /* struct */
    struct _xmlNode *left;
    struct _xmlNode *right;
};



struct _xmlDoc
{
    char vesion[XML_MAX_NODE_LEN];
    char encoding[XML_MAX_NODE_LEN];

    struct _xmlNode *head;
};


struct _xmlCtxt
{
    char *ctxt;
    char *cur;
};


#pragma pack()

xmlDocPtr    xmlParseDoc( const char *cur );
void        xmlFreeNodeEx(xmlNodePtr cur);
void        xmlDocDump(xmlDocPtr pDoc, char **txt);
void        xmlFreeNodeEx(xmlNodePtr cur);
BOOL        xmlAddNode( const char *xPath,
                     xmlDocPtr pDoc,
                     xmlNodePtr pNode );
xmlNodePtr    xmlNewNode(const char *name, const char *content,
                     const char *propName, const char *propValue);

#define xmlFreeNode(cur)    do {    \
    xmlFreeNodeEx(cur->left);        \
    free(cur);cur = NULL;            \
} while(0);



#define    xmlFreeDoc(cur)    do    {        \
    xmlFreeNodeEx(cur->head);        \
    free(cur);cur = NULL;            \
} while(0);


#endif


 

parse.cpp:

 

#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;
}

阅读(949) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

hyf1402008-07-25 16:46:56

请问你这个自己运行过吗? 我想将其解析成为普通的树,需要改动的地方是不会比较多?