0

[分享] 某知名手机平台的XML Parser源代码


    今天心情不错~ 分享一下小弟06年在某手机公司写的XML .
虽然当时脑子里还没有FSM的概念, 但代码逻辑还算清晰, 颇有成就感!
结构比较简单, 按DOM方式把指定文件解析成节点树, 另外提供几个简单的查找函数.
部分功能等完善, 过段时间再发一份功能比较完善的C++版本.

PLX_XMLParser.h

#if _MSC_VER > 1000
#pragma once
#endif

#ifndef __XMLPARSE_H
#define __XMLPARSE_H

#include

//////////////////////////////
// Configure

#define USE_INLINE_FUNCTION
#define USE_FILEBUFFER

//////////////////////////////
// Constants

typedef enum {
XMLERR_OK       = 0×0,
XMLERR_EFILE,       // failed to open file
XMLERR_ALRDOPEN,    // already opened
XMLERR_EDOC,
XMLERR_EPARSE,
} XMLERR;

typedef enum {
NODETYPE_UNKN    = 0×0,
NODETYPE_ELEM   = 0×1,
NODETYPE_TEXT   = 0×2,
NODETYPE_COMM   = 0×4,
NODETYPE_INST   = 0×8, // Not support
//NODETYPE_USEFUL = NODETYPE_ELEM|NODETYPE_TEXT,
//NODETYPE_ALL    = NODETYPE_ELEM|NODETYPE_TEXT|NODETYPE_COMM|NODETYPE_INST,
} NODETYPE;

typedef enum {
DSTAT_UNOPEN    = 0×0,
DSTAT_OPENED    = 0×1,
} DOCSTAT;

typedef enum {
ISTAT_STOP      = 0×0,
ISTAT_CONTINUE  = 0×1,
ISTAT_PASS      = 0×2,
} ITERSTAT;

enum {    MAXLEN_BSTR    = 256 };

//////////////////////////////
// Structures

struct tagBString
{
LONG    m_lLength;
union   {
CHAR    m_paStr[1];
LPCSTR  m_pszStr;
};
};

typedef struct tagBString       BSTRING;
typedef struct tagBString       *LPBSTRING;
typedef struct tagBString const *LPCBSTRING;

struct tagXMLAttrib;
typedef struct tagXMLAttrib            XMLATTRIB;
typedef struct tagXMLAttrib            *LPXMLATTRIB;
typedef struct tagXMLAttrib    const    *LPCXMLATTRIB;

struct tagXMLAttrib
{
LPBSTRING   m_pbstrName;
LPBSTRING   m_pbstrValue;
LPXMLATTRIB    m_pNext;
};

struct tagXMLNode;
typedef struct tagXMLNode       XMLNODE;
typedef struct tagXMLNode       *LPXMLNODE;
typedef struct tagXMLNode const *LPCXMLNODE;

struct tagXMLNode
{
NODETYPE    m_eNodeType;
LONG        m_lDepth;

LPBSTRING   m_pbstrTag;

LONG        m_lChildNum;
LONG        m_lChildNum_Elem;

LPXMLNODE    m_pRoot;
LPXMLNODE   m_pParent;
LPXMLNODE   m_pFirstChild;
LPXMLNODE   m_pLastChild;
LPXMLNODE   m_pPrevSibling;
LPXMLNODE   m_pNextSibling;

LONG        m_lAttribNum;
LPXMLATTRIB m_pFirstAttrib;
};

struct tagXMLDocument
{
DOCSTAT     m_eDocStat;
LPXMLNODE   m_lpRootNode;
};

typedef struct tagXMLDocument       XMLDOCUMENT;
typedef struct tagXMLDocument       *LPXMLDOCUMENT;
typedef struct tagXMLDocument const *LPCXMLDOCUMENT;

//////////////////////////////
// Types

typedef ITERSTAT    (CALLBACK *LPFNNODEPROC)( LPCXMLNODE pNode, LPVOID pvParam );

//////////////////////////////
// Macros

#if    defined(USE_INLINE_FUNCTION)

#define BSTR_C( pBStr )                     (&((pBStr)->m_paStr[0]))
#define BSTR_CAST( pvAnyType )              ((LPBSTRING)pvAnyType)
#define    BSTR_LEN( pBStr )                   ((pBStr)->m_lLength)
#define BSTR_ALLOC( pszStr )                AllocBString( pszStr, (NULL != (pszStr) ? ((LONG)strlen(pszStr)) : (0L)) )
#define BSTR_ALLOCEX( pszStr, nLen )        AllocBString( pszStr, (LONG)nLen )
#define BSTR_FREE( pBStr )                  free( pBStr )
#define BSTR_SAFEFREE( pBStr )              if ( NULL != pBStr ) { free( pBStr ); pBStr = NULL; }
#define BSTR_EQUAL( pBStrL, pBStrR ) \
( (BSTR_LEN(pBStrL) == BSTR_LEN(pBStrR) && 0 == strcmp(BSTR_C(pBStrL), BSTR_C(pBStrL))) ? \
TRUE : FALSE )
#define BSTR_EQUAL_STATIC( pBStr, szStatic ) \
( (BSTR_LEN(pBStr) == (LONG)(sizeof(szStatic) – 1) && 0 == strcmp(BSTR_C(pBStr), szStatic)) ? \
TRUE : FALSE )
#define BSTR_EQUAL_CSTR( pBStr, pszStr ) \
( (BSTR_LEN(pBStr) == (LONG)strlen(pszStr) && 0 == strcmp(BSTR_C(pBStr), pszStr)) ? \
TRUE : FALSE )

#define    _GetRootNode( pDoc )             ((NULL == (pDoc) || (pDoc)->m_eDocStat != DSTAT_OPENED) ? NULL : (pDoc)->m_lpRootNode)
#define    XML_GetNodeType( pNode )             (NULL != (pNode) ? (pNode)->m_eNodeType : NODETYPE_UNKN)
#define    XML_GetNodeDepth( pNode )            (NULL != (pNode) ? (pNode)->m_lDepth : (-1L))
#define    XML_GetNodeParent( pNode )             (NULL != (pNode) ? (pNode)->m_pParent : NULL)
#define    XML_GetNodeFirstChild( pNode )         (NULL != (pNode) ? (pNode)->m_pFirstChild : NULL)
#define    XML_GetNodeLastChild( pNode )         (NULL != (pNode) ? (pNode)->m_pLastChild : NULL)
#define    XML_GetNodeChildNum( pNode )         (NULL != (pNode) ? (pNode)->m_lChildNum : (0L))
#define    XML_GetNodeChildNum_Elem( pNode )     (NULL != (pNode) ? (pNode)->m_lChildNum_Elem : (0L))
#define    XML_GetNodePrevSibling( pNode )     (NULL != (pNode) ? (pNode)->m_pPrevSibling : NULL)
#define    XML_GetNodeNextSibling( pNode )     (NULL != (pNode) ? (pNode)->m_pNextSibling : NULL)
#define    XML_GetNodeTagName( pNode )         (NULL != (pNode) ? (pNode)->m_pbstrTag : NULL)
#define    XML_GetNodeAttribNum( pNode )         (NULL != (pNode) ? (pNode)->m_lAttribNum : (0L))
#define    XML_GetNodeFirstAttrib( pNode )     (NULL != (pNode) ? (pNode)->m_pFirstAttrib : NULL)
#define    XML_GetNodeNextAttrib( pAttr )         (NULL != (pAttr) ? (pAttr)->m_pNext : NULL)
#define XML_GetAttribValueBString( pAttr )  (NULL != (pAttr) ? (pAttr)->m_pbstrValue) : NULL)
#define XML_GetAttribValueCString( pAttr )  (NULL != (pAttr) ? BSTR_C((pAttr)->m_pbstrValue) : NULL)
#define XML_GetAttribValueLong( pAttr )     (NULL != (pAttr) ? (LONG)strtol(BSTR_C((pAttr)->m_pbstrValue), NULL, 0) : (0L))
#define XML_GetAttribValueInt( pAttr )      (NULL != (pAttr) ? (int)strtol(BSTR_C((pAttr)->m_pbstrValue), NULL, 0) : (0))

#endif

//////////////////////////////
// Function prototypes

#if defined(__cplusplus)
extern “C” {
#endif

size_t      strlen_when( LPCSTR lpszStr, CHAR ch );
size_t        strlen_notin( LPCSTR lpszStr, LPCSTR lpszSet );
LPCSTR        strchr_notin( LPCSTR lpszStr, LPCSTR lpszSet );
LPCSTR        strchr_skipws( LPCSTR lpszStr );

LPBSTRING   AllocBString( LPCSTR lpszStr, LONG lLen );

XMLERR      XML_OpenDocument( LPXMLDOCUMENT pDoc, LPCSTR lpszFileName, DWORD dwReserve );
XMLERR      XML_CloseDocument( LPXMLDOCUMENT pDoc );
LPXMLNODE    XML_GetNode( LPXMLDOCUMENT pDoc, LPXMLNODE pStartPoint, LPCSTR lpszTag, LONG lLen );
LPXMLATTRIB    XML_GetNodeAttrib( LPXMLNODE pNode, LPCSTR lpszAttr, LONG lLen );
LPXMLNODE    XML_GetNodeSibling( LPXMLNODE pNode, LPCSTR lpszTag, LONG lLen, BOOL IncludeThis );
LONG         XML_ForEachNode( LPXMLDOCUMENT pDoc, LPXMLNODE pStartPoint, LPFNNODEPROC pfnNodeProc, LPVOID pvParam );

#if defined(__cplusplus)
}   // extern “C” {
#endif

#endif // #ifndef __XMLPARSE_H

PLX_XMLParser.c

#include <assert.h>
#include <fcntl.h>
#include <io.h>
#if defined() || defined(_)
#include <stdio.h>
#endif

#include “XMLParse.h”

//#pragma warning(disable:4305)

//////////////////////////////
// Configure

//#define  USE_MEMORY_HEAP

#ifdef  USE_FILEBUFFER  // Whether use file system with os-layer buffer

#define INVALID_FILE_HANDLE         ((int)-1)
#define FILE_HANDLE                 int

#define MODE_RDONLY                 (O_RDONLY)
#define FILE_OPEN(pszFile,mode)     open( pszFile, mode )
#define FILE_READ(hFile,pbuf,size)  read(hFile, (LPVOID)pbuf, size)
#define FILE_SEEK(hFile,off,pos)    lseek( hFile, off, pos )
#define FILE_CLOSE(hFile)           close( hFile )

#else

#define INVALID_FILE_HANDLE         ((FILE *)NULL)
#define FILE_HANDLE                 FILE *

#define MODE_RDONLY                 (“r”)
#define FILE_OPEN(pszFile,mode)     fopen( pszFile, mode )
#define FILE_READ(hFile,pbuf,size)  fread((LPVOID)pbuf, size, 1, hFile)
#define FILE_SEEK(hFile,off,pos)    fseek( hFile, off, pos )
#define FILE_CLOSE(hFile)           fclose( hFile )

#endif

//////////////////////////////
// Constants

enum {    MAXLEN_READBUF    = 1024 };

typedef enum {
PSTAT_STOP      = 0×0,
PSTAT_INITIAL,
PSTAT_FINAL,
PSTAT_DECL_BEG,
PSTAT_DECL_END,
PSTAT_ELEM_BEG,
PSTAT_ELEM_END,
PSTAT_TEXT_BEG,
PSTAT_TEXT_END,
PSTAT_CDATA_BEG,
PSTAT_CDATA_END,
PSTAT_COMM_BEG,
PSTAT_COMM_END,
PSTAT_ERROR,
} PARSESTAT;

//////////////////////////////
// Macros

#define ZERO_MEMORY(p, size) \
( memset((LPVOID)(p), 0×0, (size_t)size) )

#define is_WhiteSpace(ch)   (((ch) == ‘ ‘  || (ch) == ‘\t’) ? TRUE : FALSE)
#define is_LineBreak(ch)    (((ch) == ‘\r’ || (ch) == ‘\n’) ? TRUE : FALSE)
#define is_LeftBracket(ch)    ((ch) == ‘<’ ? TRUE : FALSE)
#define is_RightBracket(ch)    ((ch) == ‘>’ ? TRUE : FALSE)

#define is_BufferEmpty(ps)  ((ps)->m_lReadCursor >= (ps)->m_lReadSize ? TRUE : FALSE)
#define get_BufferChar(ps)  ((CHAR)((ps)->m_aReadBuf[(ps)->m_lReadCursor]))

#define is_FirstChild(pn)    ((pn)->m_pPrevSibling == NULL ? TRUE : FALSE)
#define is_LastChild(pn)    ((pn)->m_pNextSibling == NULL ? TRUE : FALSE)

//////////////////////////////
// Structures

struct tagXMLParseStat
{
PARSESTAT   m_eParseStat;
LONG        m_lDepth;
LPXMLNODE    m_pRootNode;
LPXMLNODE    m_pLastNode;

FILE_HANDLE    m_hOpenFile;
LONG        m_lFileCursor;
LONG        m_lFileLength;

LONG        m_lLineNo;
LONG        m_lReadCursor;
LONG        m_lReadSize;
BYTE        m_aReadBuf[MAXLEN_READBUF];
};
typedef struct tagXMLParseStat            XMLPARSESTAT;
typedef struct tagXMLParseStat            *LPXMLPARSESTAT;
typedef struct tagXMLParseStat    const    *LPCXMLPARSESTAT;

struct tagXMLIterator
{
LONG            m_lCount;
LPFNNODEPROC    m_pfnProc;
LPVOID          m_pvParam;
LPXMLNODE       m_pStation;
};
typedef struct tagXMLIterator       XMLITERFATOR;
typedef struct tagXMLIterator       *LPXMLITERFATOR;
typedef struct tagXMLIterator const *LPCXMLITERFATOR;

/*struct tagMemoryPage
{
LONG    lGranu ;
LONG    lSize;
LPVOID  pvPage;
BYTE    bUseFlags[1];
};
typedef struct tagMemoryPage        MEMORYPAGE;
typedef struct tagMemoryPage        *LPMEMORYPAGE;
typedef struct tagMemoryPage const  *LPCMEMORYPAGE;*/

//////////////////////////////
// Function prototypes

#if defined(__cplusplus)
extern “C” {
#endif

static void        XML_FreeNodeTree( LPXMLNODE pNode );
static void        XML_FreeAttribList( LPXMLATTRIB pAttrib );
static void     XML_IterateTree( LPXMLNODE pTree, LPXMLITERFATOR pIterator );
static BOOL     XMLCmpNode_EqualTag( LPCXMLNODE pNode, LPVOID pvParam );

static BOOL        Parser_RoutineStart( LPXMLPARSESTAT pParseStat, LPXMLDOCUMENT pResult );
static int        Parser_GetTagString( LPXMLPARSESTAT pParseStat, LPSTR lpszBuf );
static BOOL        Parser_ReadStream( LPXMLPARSESTAT pParseStat );
static void        Parser_OnInitial( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static void        Parser_OnElemBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static void        Parser_OnElemEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static void        Parser_OnTextBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static void        Parser_OnTextEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static void        Parser_OnCDATABegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static void        Parser_OnCDATAEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static void        Parser_OnCommBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static void        Parser_OnCommEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static void        Parser_OnDeclBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static void        Parser_OnDeclEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );
static BOOL        Parser_OnFinal( LPXMLPARSESTAT pParseStat );
static BOOL        Parser_OnError( LPXMLPARSESTAT pParseStat );

//#if defined(USE_MEMORY_HEAP)
//static LPVOID   MemoryHeap_Create( LONG lInitialGranu, LONG lInitialSize );
//static BOOL     MemoryHeap_Destroy( LPVOID );
//static LPVOID   MemoryHeap_Alloc( void );
//static void     MemoryHeap_Free( LPVOID pvBlock );
//#endif

#if defined(__cplusplus)
}   // extern “C” {
#endif

//////////////////////////////
// Function implementations

#if defined(__cplusplus)
extern “C” {
#endif

/*********************************************************************\
* Function: strlen_when
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
size_t strlen_when( LPCSTR lpszStr, CHAR ch )
{
register size_t nLen;
assert( NULL != lpszStr );
for ( nLen = 0; *lpszStr != ch && *lpszStr != ‘\0′;    lpszStr++, nLen++ )
;
return nLen;
}

/*********************************************************************\
* Function: strlen_notin
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
size_t strlen_notin( LPCSTR lpszStr, LPCSTR lpszSet )
{
register size_t nLen;
assert( NULL != lpszStr );
for ( nLen = 0; *lpszStr != ‘\0′ && NULL == strchr(lpszSet, *lpszStr); lpszStr++, nLen++ )
;
return nLen;
}

/*********************************************************************\
* Function: strchr_notin
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
LPCSTR strchr_notin( LPCSTR lpszStr, LPCSTR lpszSet )
{
assert( NULL != lpszStr );
for ( ; *lpszStr != ‘\0′ && NULL == strchr(lpszSet, *lpszStr); lpszStr++ )
;
return lpszStr;
}

/*********************************************************************\
* Function: strchr_skipws
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
LPCSTR strchr_skipws( LPCSTR lpszStr )
{
assert( NULL != lpszStr );
for ( ; *lpszStr != ‘\0′ && is_WhiteSpace(*lpszStr); lpszStr++ )
;
return lpszStr;
}

/*********************************************************************\
* Function: AllocBString
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
LPBSTRING AllocBString( LPCSTR lpszStr, LONG lLen )
{
LPBSTRING pBStr = (LPBSTRING)malloc( sizeof(LONG) + lLen + 1 );
assert( NULL != pBStr );

pBStr->m_lLength = lLen;
strncpy( &pBStr->m_paStr[0], lpszStr, lLen );
pBStr->m_paStr[lLen] = ‘\0′;

return pBStr;
}

/*********************************************************************\
* Function: XML_OpenDocument
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
XMLERR XML_OpenDocument( LPXMLDOCUMENT pDoc, LPCSTR lpszFileName, DWORD dwReserve )
{
BOOL            bRet;
FILE_HANDLE        hFile;
XMLPARSESTAT    xmlParseStat;

assert( NULL != pDoc );
assert( NULL != lpszFileName );

if ( pDoc->m_eDocStat == DSTAT_OPENED )
return XMLERR_ALRDOPEN;

ZERO_MEMORY( &xmlParseStat, sizeof(XMLPARSESTAT) );

hFile = FILE_OPEN( lpszFileName, MODE_RDONLY );
if ( INVALID_FILE_HANDLE == hFile )
return XMLERR_EFILE;

xmlParseStat.m_hOpenFile    = hFile;
xmlParseStat.m_lFileCursor    = 0;
xmlParseStat.m_lFileLength    = FILE_SEEK( hFile, 0, SEEK_END );
FILE_SEEK( hFile, 0, SEEK_SET );

xmlParseStat.m_lDepth = 0;
xmlParseStat.m_lLineNo = 1;
bRet = Parser_RoutineStart( &xmlParseStat, pDoc );
if ( FALSE == bRet )
{
FILE_CLOSE( hFile );
return XMLERR_EPARSE;
}

pDoc->m_eDocStat    = DSTAT_OPENED;
pDoc->m_lpRootNode    = xmlParseStat.m_pRootNode;
FILE_CLOSE( hFile );
return XMLERR_OK;
}

/*********************************************************************\
* Function: XML_CloseDocument
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
XMLERR XML_CloseDocument( LPXMLDOCUMENT pDoc )
{
if ( NULL != pDoc && pDoc->m_eDocStat == DSTAT_OPENED )
{
XML_FreeNodeTree( pDoc->m_lpRootNode );
pDoc->m_lpRootNode = NULL;
pDoc->m_eDocStat = DSTAT_UNOPEN;
}
return XMLERR_OK;
}

/*********************************************************************\
* Function: Parser_GetTagString
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
int Parser_GetTagString( LPXMLPARSESTAT pParseStat, LPSTR lpszBuf )
{
int        nLen;
CHAR    ch;
CHAR    chTerm;
BOOL    bInclude;

// Should to ensure barket match Here!

nLen = 0;
for ( ;; )
{
if ( is_BufferEmpty(pParseStat) && FALSE == Parser_ReadStream(pParseStat) )
goto __RET;

ch = get_BufferChar(pParseStat);
if ( ch == ‘\n’ )
pParseStat->m_lLineNo++;

if ( !is_WhiteSpace(ch) && !is_LineBreak(ch) )
break;

pParseStat->m_lReadCursor++;
}

if ( is_LeftBracket(ch) )
{
chTerm = ‘>’;
bInclude = TRUE;
}
else
{
chTerm = ‘<’;
bInclude = FALSE;
}

for ( ;; )
{
if ( is_BufferEmpty(pParseStat) && FALSE == Parser_ReadStream(pParseStat) )
break;

ch = get_BufferChar(pParseStat);
if ( ch == ‘\n’ )
pParseStat->m_lLineNo++;

if ( ch == chTerm )
{
if ( FALSE != bInclude )
{
lpszBuf[nLen++] = chTerm;
pParseStat->m_lReadCursor++;
}
break;
}

lpszBuf[nLen++] = ch;
pParseStat->m_lReadCursor++;
}

__RET:
lpszBuf[nLen] = ‘\0′;
return nLen;
}

/*********************************************************************\
* Function: Parser_ReadStream
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
BOOL Parser_ReadStream( LPXMLPARSESTAT pParseStat )
{
size_t    nSize;

pParseStat->m_lReadCursor    = 0;
pParseStat->m_lReadSize    = 0;
nSize = FILE_READ( pParseStat->m_hOpenFile, (LPVOID)&pParseStat->m_aReadBuf[0], MAXLEN_READBUF );
if ( nSize <= 0 )
return FALSE;

pParseStat->m_lReadSize        = (LONG)nSize;
pParseStat->m_lFileCursor  += (LONG)nSize;
return TRUE;
}

/*********************************************************************\
* Function: Parser_RoutineStart
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
BOOL Parser_RoutineStart( LPXMLPARSESTAT pParseStat, LPXMLDOCUMENT pResult )
{
BOOL    bRet;
CHAR    szTag[256];

assert( NULL != pParseStat );

pParseStat->m_eParseStat = PSTAT_INITIAL;
while ( pParseStat->m_eParseStat != PSTAT_STOP )
{
switch ( pParseStat->m_eParseStat )
{
case PSTAT_INITIAL:     Parser_OnInitial( pParseStat, &szTag[0] );        break;

case PSTAT_DECL_BEG:    Parser_OnDeclBegin( pParseStat, &szTag[0] );    break;
case PSTAT_DECL_END:    Parser_OnDeclEnd( pParseStat, &szTag[0] );        break;

case PSTAT_ELEM_BEG:    Parser_OnElemBegin( pParseStat, &szTag[0] );    break;
case PSTAT_ELEM_END:    Parser_OnElemEnd( pParseStat, &szTag[0] );      break;

case PSTAT_TEXT_BEG:    Parser_OnTextBegin( pParseStat, &szTag[0] );    break;
case PSTAT_TEXT_END:    Parser_OnTextEnd( pParseStat, &szTag[0] );        break;

case PSTAT_CDATA_BEG:    Parser_OnCDATABegin( pParseStat, &szTag[0] );    break;
case PSTAT_CDATA_END:    Parser_OnCDATAEnd( pParseStat, &szTag[0] );        break;

case PSTAT_COMM_BEG:    Parser_OnCommBegin( pParseStat, &szTag[0] );    break;
case PSTAT_COMM_END:    Parser_OnCommEnd( pParseStat, &szTag[0] );        break;

case PSTAT_FINAL:        bRet = Parser_OnFinal( pParseStat );            break;
case PSTAT_ERROR:        bRet = Parser_OnError( pParseStat );            break;

default:
assert( !”Unknown parsing status!” );
break;
}
}
return bRet;
}

/*********************************************************************\
* Function: Parser_OnInitial
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnInitial( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
int     nLen;
assert( NULL != lpszTag );

lpszTag[0] = ‘\0′;

nLen = Parser_GetTagString( pParseStat, lpszTag );
if ( nLen <= 0 )
{
pParseStat->m_eParseStat = PSTAT_STOP;
return;
}

if ( lpszTag[0] == ‘<’  )
{
if ( lpszTag[1] == ‘?’)
{
pParseStat->m_eParseStat = PSTAT_DECL_BEG;
}
else if ( !strncmp(&lpszTag[1], “!–”, 3) )
{
pParseStat->m_eParseStat = PSTAT_COMM_BEG;
}
else if ( lpszTag[1] == ‘/’ )
{
pParseStat->m_eParseStat = PSTAT_ELEM_END;
}
else if ( isalpha(lpszTag[1]) )
{
pParseStat->m_eParseStat = PSTAT_ELEM_BEG;
}
else if ( !strncmp(&lpszTag[1], “![CDATA[", 8) )
{
pParseStat->m_eParseStat = PSTAT_CDATA_BEG;
}
else
{
pParseStat->m_eParseStat = PSTAT_ERROR;
}
}
else if ( NULL != pParseStat->m_pLastNode )
{
pParseStat->m_eParseStat = PSTAT_TEXT_BEG;
}
else
{
pParseStat->m_eParseStat = PSTAT_ERROR;
}
}

/*********************************************************************\
* Function: Parser_OnFinal
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
BOOL Parser_OnFinal( LPXMLPARSESTAT pParseStat )
{
pParseStat->m_eParseStat = PSTAT_STOP;
return TRUE;
}

/*********************************************************************\
* Function: Parser_OnError
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
BOOL Parser_OnError( LPXMLPARSESTAT pParseStat )
{
XML_FreeNodeTree( pParseStat->m_pRootNode );
pParseStat->m_pRootNode     = NULL;
pParseStat->m_eParseStat = PSTAT_STOP;
TRACE( "[Xml Parser]: Syntax error @ %s #%ld.\n”, “”, pParseStat->m_lLineNo);
return FALSE;
}

/*********************************************************************\
* Function: Parser_OnDeclBegin
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnDeclBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
int nLenTag;

if ( NULL != pParseStat->m_pRootNode )
{
pParseStat->m_eParseStat = PSTAT_ERROR;
return;
}

lpszTag = (LPSTR)strchr_skipws( (LPCSTR)(lpszTag + 2) );
if ( lpszTag == ‘\0′ )
{
pParseStat->m_eParseStat = PSTAT_ERROR;
return;
}

nLenTag = (int)strlen_notin(lpszTag, ” \t\r\n>”);
if ( nLenTag == 3 && !strncmp(lpszTag, “xml”, 3) )
{
// Here, dispose version and coding infomation in XML document header
}
else if ( nLenTag == 14 && !strncmp(lpszTag, “xml-stylesheet”, 3) )
{
// Unsupport
}
else
{
// Unknown declaretion
}

pParseStat->m_eParseStat = PSTAT_INITIAL;
}

/*********************************************************************\
* Function: Parser_OnDeclEnd
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnDeclEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
// Do noting
}

/*********************************************************************\
* Function: Parser_OnElemBegin
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnElemBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
int         nLenTag;
int         nLenValue;
LPSTR       lpszValue;
LPXMLNODE   pNode;
LPXMLATTRIB    pAttrib;
LPXMLATTRIB pPrevAttr;

assert( is_LeftBracket(lpszTag[0]) );

// Multi-root node is not supproted
if ( 0 == pParseStat->m_lDepth && NULL != pParseStat->m_pRootNode )
goto __ERROR;

pNode = (LPXMLNODE)malloc(sizeof(XMLNODE));
if ( NULL == pNode )
goto __ERROR;

ZERO_MEMORY( pNode, sizeof(XMLNODE) );
pNode->m_eNodeType    = NODETYPE_ELEM;
pNode->m_lDepth        = pParseStat->m_lDepth;
if ( NULL != pParseStat->m_pLastNode )
{
assert( pNode->m_lDepth >= pParseStat->m_pLastNode->m_lDepth );
if ( pNode->m_lDepth > pParseStat->m_pLastNode->m_lDepth ) // new child
{
pNode->m_pParent = pParseStat->m_pLastNode;
pParseStat->m_pLastNode->m_pFirstChild = pNode;
}
else if ( pNode->m_lDepth == pParseStat->m_pLastNode->m_lDepth ) // new sibling
{
pNode->m_pParent = pParseStat->m_pLastNode->m_pParent;
pParseStat->m_pLastNode->m_pNextSibling = pNode;
pNode->m_pPrevSibling = pParseStat->m_pLastNode;
}

if ( NULL != pNode->m_pParent )
{
pNode->m_pParent->m_lChildNum++;
pNode->m_pParent->m_lChildNum_Elem++;
}
}

if ( NULL == pParseStat->m_pRootNode )
{
pParseStat->m_pRootNode = pNode;
}
pNode->m_pRoot = pParseStat->m_pRootNode;

pParseStat->m_pLastNode    = pNode;

lpszTag++;
nLenTag = (int)strlen_notin(lpszTag, ” \t\r\n>”);
if ( nLenTag <= 0 )
goto __ERROR;

pNode->m_pbstrTag = BSTR_ALLOCEX(lpszTag, nLenTag);
if ( NULL == pNode->m_pbstrTag )
goto __ERROR;

lpszTag = (LPSTR)(lpszTag + nLenTag);

for ( pPrevAttr = NULL;; )
{
lpszTag = (LPSTR)strchr_skipws( lpszTag );

if ( is_RightBracket(*lpszTag) )
{
pParseStat->m_lDepth++; // Move down one layer
pParseStat->m_eParseStat = PSTAT_INITIAL;
break;
}
else if ( !strncmp(lpszTag, “/>”, 2) )
{
//pParseStat->m_lDepth–; //
pParseStat->m_eParseStat = PSTAT_INITIAL;
break;
}

nLenTag = (int)strlen_when( lpszTag, ‘=’ );
if ( nLenTag <= 0 )
goto __ERROR;

lpszValue = strchr( (LPCSTR)(lpszTag + nLenTag), ‘\”‘ );
if ( NULL == lpszValue )
goto __ERROR;

lpszValue++;
nLenValue = (int)strlen_when( lpszValue, ‘\”‘ );

//if ( nLenValue <= 0 )
//    goto __ERROR;

pAttrib = (LPXMLATTRIB)malloc(sizeof(XMLATTRIB));
if ( NULL == pAttrib )
goto __ERROR;
ZERO_MEMORY( pAttrib, sizeof(XMLATTRIB) );

pAttrib->m_pbstrName    = BSTR_ALLOCEX( lpszTag, nLenTag );
pAttrib->m_pbstrValue    = BSTR_ALLOCEX( lpszValue, nLenValue );
if ( NULL == pAttrib->m_pbstrName || NULL == pAttrib->m_pbstrValue )
goto __ERROR;

if ( NULL == pNode->m_pFirstAttrib )
pNode->m_pFirstAttrib = pAttrib;

if ( NULL != pPrevAttr )
pPrevAttr->m_pNext = pAttrib;
pPrevAttr = pAttrib;

pNode->m_lAttribNum++;
lpszTag = lpszValue + nLenValue + 1;
}

return;

__ERROR:
XML_FreeNodeTree( pNode );
pParseStat->m_eParseStat = PSTAT_ERROR;
}

/*********************************************************************\
* Function: Parser_OnElemEnd
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnElemEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
pParseStat->m_lDepth–;

if ( NULL != pParseStat->m_pLastNode )
{
if ( NULL != pParseStat->m_pLastNode->m_pParent )
pParseStat->m_pLastNode->m_pParent->m_pLastChild = pParseStat->m_pLastNode;

if ( pParseStat->m_pLastNode->m_lDepth > pParseStat->m_lDepth )
pParseStat->m_pLastNode = pParseStat->m_pLastNode->m_pParent;
}

if ( 0 == pParseStat->m_lDepth )
pParseStat->m_eParseStat = PSTAT_FINAL;
else
pParseStat->m_eParseStat = PSTAT_INITIAL;
}

/*********************************************************************\
* Function: Parser_OnTextBegin
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnTextBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
LPXMLNODE pNode;

pNode = (LPXMLNODE)malloc(sizeof(XMLNODE));
if ( NULL == pParseStat->m_pLastNode )
goto __ERROR;

ZERO_MEMORY( pNode, sizeof(XMLNODE) );
pNode->m_eNodeType    = NODETYPE_TEXT;
pNode->m_lDepth        = pParseStat->m_lDepth;

if ( NULL != pParseStat->m_pLastNode )
{
assert( pNode->m_lDepth >= pParseStat->m_pLastNode->m_lDepth );
if ( pNode->m_lDepth > pParseStat->m_pLastNode->m_lDepth )
{
pNode->m_pParent = pParseStat->m_pLastNode;
pParseStat->m_pLastNode->m_pFirstChild = pNode;
}
else if ( pNode->m_lDepth == pParseStat->m_pLastNode->m_lDepth )
{
pNode->m_pParent = pParseStat->m_pLastNode->m_pParent;
pParseStat->m_pLastNode->m_pNextSibling = pNode;
pNode->m_pPrevSibling = pParseStat->m_pLastNode;
}

if ( NULL != pNode->m_pParent )
pNode->m_pParent->m_lChildNum++;

pNode->m_pRoot = pParseStat->m_pLastNode->m_pRoot;
}

pParseStat->m_pLastNode    = pNode;

pNode->m_pbstrTag = BSTR_ALLOC(lpszTag);
if ( NULL == pNode->m_pbstrTag )
goto __ERROR;

pParseStat->m_lDepth++; // Move down one layer
pParseStat->m_eParseStat = PSTAT_TEXT_END;
return;

__ERROR:
XML_FreeNodeTree( pNode );
pParseStat->m_eParseStat = PSTAT_ERROR;
}

/*********************************************************************\
* Function: Parser_OnTextEnd
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnTextEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
// Move up one layer
pParseStat->m_lDepth–;

if ( NULL != pParseStat->m_pLastNode &&
pParseStat->m_pLastNode->m_lDepth > pParseStat->m_lDepth )
pParseStat->m_pLastNode = pParseStat->m_pLastNode->m_pParent;

pParseStat->m_eParseStat = PSTAT_INITIAL;
}

/*********************************************************************\
* Function: Parser_OnCommBegin
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnCommBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
pParseStat->m_eParseStat = PSTAT_INITIAL;
}

/*********************************************************************\
* Function: Parser_OnCommEnd
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnCommEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
}

/*********************************************************************\
* Function: Parser_OnCDATABegin
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnCDATABegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
pParseStat->m_eParseStat = PSTAT_INITIAL;
// Should convert to text here
}

/*********************************************************************\
* Function: Parser_OnCDATAEnd
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void Parser_OnCDATAEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )
{
}

/*********************************************************************\
* Function: XML_IterateTree
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void XML_IterateTree( LPXMLNODE pTree, LPXMLITERFATOR pIterator )
{
register ITERSTAT eStat;
if ( NULL != pTree )
{
pIterator->m_pStation = pTree;
eStat = pIterator->m_pfnProc( pTree, pIterator->m_pvParam );
if ( eStat == ISTAT_STOP )
return;
if ( eStat != ISTAT_PASS )
pIterator->m_lCount++;

XML_IterateTree( pTree->m_pFirstChild, pIterator );
XML_IterateTree( pTree->m_pNextSibling, pIterator );
}
}

/*********************************************************************\
* Function: XML_ForEachNode
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
LONG XML_ForEachNode( LPXMLDOCUMENT pDoc, LPXMLNODE pStartPoint, LPFNNODEPROC pfnNodeProc, LPVOID pvParam )
{
XMLITERFATOR    iter;

assert( NULL != pDoc );
assert( NULL != pfnNodeProc );

if ( pDoc->m_eDocStat == DSTAT_UNOPEN || (NULL != pStartPoint && pStartPoint->m_pRoot != pDoc->m_lpRootNode) )
return 0;

iter.m_lCount   = 0;
iter.m_pStation = NULL;
iter.m_pvParam  = pvParam;
iter.m_pfnProc  = pfnNodeProc;

pStartPoint = (NULL == pStartPoint ? pDoc->m_lpRootNode : pStartPoint);
XML_IterateTree( pStartPoint, &iter );
return iter.m_lCount;
}

/*********************************************************************\
* Function: XMLCmpNode_EqualTag
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
ITERSTAT XMLCmpNode_EqualTag( LPCXMLNODE pNode, LPVOID pvParam )
{
if ( FALSE != BSTR_EQUAL(pNode->m_pbstrTag, BSTR_CAST(pvParam)) )
return ISTAT_STOP;
else
return ISTAT_CONTINUE;
}

/*********************************************************************\
* Function: XML_GetNode
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
LPXMLNODE XML_GetNode( LPXMLDOCUMENT pDoc, LPXMLNODE pStartPoint, LPCSTR lpszTag, LONG lLen )
{
BSTRING         bStr;
XMLITERFATOR    iter;

assert( NULL != lpszTag );
assert( NULL != pDoc );

if ( pDoc->m_eDocStat == DSTAT_UNOPEN || pStartPoint->m_pRoot != pDoc->m_lpRootNode )
return NULL;

bStr.m_lLength  = lLen;
bStr.m_pszStr   = lpszTag;

iter.m_lCount   = 0;
iter.m_pfnProc  = &XMLCmpNode_EqualTag;
iter.m_pStation = NULL;
iter.m_pvParam  = (LPVOID)&bStr;

pStartPoint = (NULL == pStartPoint ? pDoc->m_lpRootNode : pStartPoint);
XML_IterateTree( pStartPoint, &iter );
return (iter.m_pStation);
}

/*********************************************************************\
* Function: XML_GetNodeAttrib
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
LPXMLATTRIB    XML_GetNodeAttrib( LPXMLNODE pNode, LPCSTR lpszAttr, LONG lLen )
{
BSTRING     bStr;
LPXMLATTRIB pAttrib;

assert( NULL != lpszAttr );
assert( NULL != pNode );
bStr.m_lLength  = lLen;
bStr.m_pszStr   = lpszAttr;

for ( pAttrib = XML_GetNodeFirstAttrib(pNode); NULL != pAttrib; pAttrib = XML_GetNodeNextAttrib(pAttrib) )
{
if ( FALSE != BSTR_EQUAL(pAttrib->m_pbstrName, &bStr) )
break;
}

return pAttrib;
}

/*********************************************************************\
* Function: XML_GetNodeSibling
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
LPXMLNODE XML_GetNodeSibling( LPXMLNODE pNode, LPCSTR lpszTag, LONG lLen, BOOL bIncludeThis )
{
BSTRING     bStr;

assert( NULL != lpszTag );
assert( NULL != pNode );
bStr.m_lLength  = lLen;
bStr.m_pszStr   = lpszTag;

if ( FALSE != bIncludeThis && FALSE != BSTR_EQUAL(pNode->m_pbstrTag, &bStr) )
return pNode;

for ( pNode = XML_GetNodeNextSibling(pNode); NULL != pNode; pNode = XML_GetNodeNextSibling(pNode) )
{
if ( FALSE != BSTR_EQUAL(pNode->m_pbstrTag, &bStr) )
break;
}

return pNode;
}

/*********************************************************************\
* Function: XML_FreeNodeTree
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void XML_FreeNodeTree( LPXMLNODE pNode )
{
if ( NULL != pNode )
{
BSTR_FREE( pNode->m_pbstrTag );

XML_FreeAttribList( pNode->m_pFirstAttrib );

if ( is_FirstChild(pNode) && NULL != pNode->m_pParent )
pNode->m_pParent->m_pFirstChild = pNode->m_pNextSibling;

if ( NULL != pNode->m_pNextSibling )
pNode->m_pNextSibling->m_pPrevSibling = pNode->m_pPrevSibling;
if ( NULL != pNode->m_pPrevSibling )
pNode->m_pPrevSibling->m_pNextSibling = pNode->m_pNextSibling;

XML_FreeNodeTree( pNode->m_pFirstChild );
XML_FreeNodeTree( pNode->m_pNextSibling );

free( pNode );
}
}

/*********************************************************************\
* Function: XML_FreeAttribList
* Purpose:
* Params:
* Return
* Remarks
**********************************************************************/
void XML_FreeAttribList( LPXMLATTRIB pAttrib )
{
LPXMLATTRIB pNext;

while ( NULL != pAttrib )
{
pNext = pAttrib->m_pNext;
BSTR_FREE( pAttrib->m_pbstrName );
BSTR_FREE( pAttrib->m_pbstrValue );
free( pAttrib );
pAttrib = pNext;
}
}

#if defined(__cplusplus)
}   // extern “C” {
#endif

Random Posts Recent Comments

  • 女友糖尿病害我蛀牙 Says:

    汗一个…...

  • Htj06 Says:

    zhenyouchuangyi...

  • 电商圈 Says:

    试图该怎么建立啊,,怎在程序中是吸纳...

  • edward Says:

    看得人心旷神怡,好文,情不自禁的顶一下...

  • Daniel Says:

    我也在处理这个问题,没有找到好的方法。我用了楼上兄弟的方法,还是可以的。不知道您找到好的方法了吗、我暂时楼上兄弟的方法。...

  • 卡,卡 Says:

    弱弱问一句:博主,你博客的模板这样设计pv高吗?...

  • 站长工具 Says:

    博主,兔年快乐!...

  • health Says:

    great post!!I hope I can read more in your website....

  • pdu Says:

    好博文,支持分享...

  • 站长工具 Says:

    博主的文章很不错,我是站长工具-站长精灵的作者,一款专业的SEO工具软件(可以帮您提高博客的流量),想跟您交换个链接,不知可否...

Tag Cloud

arm audio blog brew cache class debug flash google html j2me java javascript Joke linux lua mobile mtk php python ror ruby server shell stream unix web windows 优化 动态加载 女人 女生 平台 开发 手机 技术 流媒体 测试 漫画 生活 男人 男生 缓存 芯片