<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Computer, Electron and Technology &#187; xml</title>
	<atom:link href="http://www.donevii.com/post/tag/xml/feed" rel="self" type="application/rss+xml" />
	<link>http://www.donevii.com</link>
	<description>关注技术、移动互联网以及一切 GEEK &#38; NERD 的事情</description>
	<lastBuildDate>Wed, 21 Dec 2011 10:49:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>[分享] 某知名手机平台的XML Parser源代码</title>
		<link>http://www.donevii.com/post/353.html</link>
		<comments>http://www.donevii.com/post/353.html#comments</comments>
		<pubDate>Sun, 25 Nov 2007 06:21:27 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[c/c++/c#]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[parser]]></category>
		<category><![CDATA[ror]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[平台]]></category>
		<category><![CDATA[手机]]></category>
		<category><![CDATA[源代码]]></category>

		<guid isPermaLink="false">http://www.donevii.com/post/353.html</guid>
		<description><![CDATA[    今天心情不错~ 分享一下小弟06年在某手机公司写的XML parser. 虽然当时脑子里还没有FSM的概念, 但代码逻辑还算清晰, 颇有成就感! 结构比较简单, 按DOM方式把指定文件解析成节点树, 另外提... ]]></description>
			<content:encoded><![CDATA[<p>    今天心情不错~ 分享一下小弟06年在某手机公司写的XML <a href="http://www.donevii.com/post/tag/parser" class="st_tag internal_tag" rel="tag" title="Posts tagged with parser">parser</a>.<br />
虽然当时脑子里还没有FSM的概念, 但代码逻辑还算清晰, 颇有成就感!<br />
结构比较简单, 按DOM方式把指定文件解析成节点树, 另外提供几个简单的查找函数.<br />
部分功能等完善, 过段时间再发一份功能比较完善的C++版本.</p>
<h3><strong>PLX_XMLParser.h</strong></h3>
<p>#if _MSC_VER &gt; 1000<br />
#pragma once<br />
#endif</p>
<p>#ifndef __XMLPARSE_H<br />
#define __XMLPARSE_H</p>
<p>#include</p>
<p>//////////////////////////////<br />
// Configure</p>
<p>#define USE_INLINE_FUNCTION<br />
#define USE_FILEBUFFER</p>
<p>//////////////////////////////<br />
// Constants</p>
<p>typedef enum {<br />
XMLERR_OK       = 0&#215;0,<br />
XMLERR_EFILE,       // failed to open file<br />
XMLERR_ALRDOPEN,    // already opened<br />
XMLERR_EDOC,<br />
XMLERR_EPARSE,<br />
} XMLERR;</p>
<p>typedef enum {<br />
NODETYPE_UNKN    = 0&#215;0,<br />
NODETYPE_ELEM   = 0&#215;1,<br />
NODETYPE_TEXT   = 0&#215;2,<br />
NODETYPE_COMM   = 0&#215;4,<br />
NODETYPE_INST   = 0&#215;8, // Not support<br />
//NODETYPE_USEFUL = NODETYPE_ELEM|NODETYPE_TEXT,<br />
//NODETYPE_ALL    = NODETYPE_ELEM|NODETYPE_TEXT|NODETYPE_COMM|NODETYPE_INST,<br />
} NODETYPE;</p>
<p>typedef enum {<br />
DSTAT_UNOPEN    = 0&#215;0,<br />
DSTAT_OPENED    = 0&#215;1,<br />
} DOCSTAT;</p>
<p>typedef enum {<br />
ISTAT_STOP      = 0&#215;0,<br />
ISTAT_CONTINUE  = 0&#215;1,<br />
ISTAT_PASS      = 0&#215;2,<br />
} ITERSTAT;</p>
<p>enum {    MAXLEN_BSTR    = 256 };</p>
<p>//////////////////////////////<br />
// Structures</p>
<p>struct tagBString<br />
{<br />
LONG    m_lLength;<br />
union   {<br />
CHAR    m_paStr[1];<br />
LPCSTR  m_pszStr;<br />
};<br />
};</p>
<p>typedef struct tagBString       BSTRING;<br />
typedef struct tagBString       *LPBSTRING;<br />
typedef struct tagBString const *LPCBSTRING;</p>
<p>struct tagXMLAttrib;<br />
typedef struct tagXMLAttrib            XMLATTRIB;<br />
typedef struct tagXMLAttrib            *LPXMLATTRIB;<br />
typedef struct tagXMLAttrib    const    *LPCXMLATTRIB;</p>
<p>struct tagXMLAttrib<br />
{<br />
LPBSTRING   m_pbstrName;<br />
LPBSTRING   m_pbstrValue;<br />
LPXMLATTRIB    m_pNext;<br />
};</p>
<p>struct tagXMLNode;<br />
typedef struct tagXMLNode       XMLNODE;<br />
typedef struct tagXMLNode       *LPXMLNODE;<br />
typedef struct tagXMLNode const *LPCXMLNODE;</p>
<p>struct tagXMLNode<br />
{<br />
NODETYPE    m_eNodeType;<br />
LONG        m_lDepth;</p>
<p>LPBSTRING   m_pbstrTag;</p>
<p>LONG        m_lChildNum;<br />
LONG        m_lChildNum_Elem;</p>
<p>LPXMLNODE    m_pRoot;<br />
LPXMLNODE   m_pParent;<br />
LPXMLNODE   m_pFirstChild;<br />
LPXMLNODE   m_pLastChild;<br />
LPXMLNODE   m_pPrevSibling;<br />
LPXMLNODE   m_pNextSibling;</p>
<p>LONG        m_lAttribNum;<br />
LPXMLATTRIB m_pFirstAttrib;<br />
};</p>
<p>struct tagXMLDocument<br />
{<br />
DOCSTAT     m_eDocStat;<br />
LPXMLNODE   m_lpRootNode;<br />
};</p>
<p>typedef struct tagXMLDocument       XMLDOCUMENT;<br />
typedef struct tagXMLDocument       *LPXMLDOCUMENT;<br />
typedef struct tagXMLDocument const *LPCXMLDOCUMENT;</p>
<p>//////////////////////////////<br />
// Types</p>
<p>typedef ITERSTAT    (CALLBACK *LPFNNODEPROC)( LPCXMLNODE pNode, LPVOID pvParam );</p>
<p>//////////////////////////////<br />
// Macros</p>
<p>#if    defined(USE_INLINE_FUNCTION)</p>
<p>#define BSTR_C( pBStr )                     (&amp;((pBStr)-&gt;m_paStr[0]))<br />
#define BSTR_CAST( pvAnyType )              ((LPBSTRING)pvAnyType)<br />
#define    BSTR_LEN( pBStr )                   ((pBStr)-&gt;m_lLength)<br />
#define BSTR_ALLOC( pszStr )                AllocBString( pszStr, (NULL != (pszStr) ? ((LONG)strlen(pszStr)) : (0L)) )<br />
#define BSTR_ALLOCEX( pszStr, nLen )        AllocBString( pszStr, (LONG)nLen )<br />
#define BSTR_FREE( pBStr )                  free( pBStr )<br />
#define BSTR_SAFEFREE( pBStr )              if ( NULL != pBStr ) { free( pBStr ); pBStr = NULL; }<br />
#define BSTR_EQUAL( pBStrL, pBStrR ) \<br />
( (BSTR_LEN(pBStrL) == BSTR_LEN(pBStrR) &amp;&amp; 0 == strcmp(BSTR_C(pBStrL), BSTR_C(pBStrL))) ? \<br />
TRUE : FALSE )<br />
#define BSTR_EQUAL_STATIC( pBStr, szStatic ) \<br />
( (BSTR_LEN(pBStr) == (LONG)(sizeof(szStatic) &#8211; 1) &amp;&amp; 0 == strcmp(BSTR_C(pBStr), szStatic)) ? \<br />
TRUE : FALSE )<br />
#define BSTR_EQUAL_CSTR( pBStr, pszStr ) \<br />
( (BSTR_LEN(pBStr) == (LONG)strlen(pszStr) &amp;&amp; 0 == strcmp(BSTR_C(pBStr), pszStr)) ? \<br />
TRUE : FALSE )</p>
<p>#define    <a href="http://www.donevii.com/post/tag/xml" class="st_tag internal_tag" rel="tag" title="Posts tagged with xml">XML</a>_GetRootNode( pDoc )             ((NULL == (pDoc) || (pDoc)-&gt;m_eDocStat != DSTAT_OPENED) ? NULL : (pDoc)-&gt;m_lpRootNode)<br />
#define    XML_GetNodeType( pNode )             (NULL != (pNode) ? (pNode)-&gt;m_eNodeType : NODETYPE_UNKN)<br />
#define    XML_GetNodeDepth( pNode )            (NULL != (pNode) ? (pNode)-&gt;m_lDepth : (-1L))<br />
#define    XML_GetNodeParent( pNode )             (NULL != (pNode) ? (pNode)-&gt;m_pParent : NULL)<br />
#define    XML_GetNodeFirstChild( pNode )         (NULL != (pNode) ? (pNode)-&gt;m_pFirstChild : NULL)<br />
#define    XML_GetNodeLastChild( pNode )         (NULL != (pNode) ? (pNode)-&gt;m_pLastChild : NULL)<br />
#define    XML_GetNodeChildNum( pNode )         (NULL != (pNode) ? (pNode)-&gt;m_lChildNum : (0L))<br />
#define    XML_GetNodeChildNum_Elem( pNode )     (NULL != (pNode) ? (pNode)-&gt;m_lChildNum_Elem : (0L))<br />
#define    XML_GetNodePrevSibling( pNode )     (NULL != (pNode) ? (pNode)-&gt;m_pPrevSibling : NULL)<br />
#define    XML_GetNodeNextSibling( pNode )     (NULL != (pNode) ? (pNode)-&gt;m_pNextSibling : NULL)<br />
#define    XML_GetNodeTagName( pNode )         (NULL != (pNode) ? (pNode)-&gt;m_pbstrTag : NULL)<br />
#define    XML_GetNodeAttribNum( pNode )         (NULL != (pNode) ? (pNode)-&gt;m_lAttribNum : (0L))<br />
#define    XML_GetNodeFirstAttrib( pNode )     (NULL != (pNode) ? (pNode)-&gt;m_pFirstAttrib : NULL)<br />
#define    XML_GetNodeNextAttrib( pAttr )         (NULL != (pAttr) ? (pAttr)-&gt;m_pNext : NULL)<br />
#define XML_GetAttribValueBString( pAttr )  (NULL != (pAttr) ? (pAttr)-&gt;m_pbstrValue) : NULL)<br />
#define XML_GetAttribValueCString( pAttr )  (NULL != (pAttr) ? BSTR_C((pAttr)-&gt;m_pbstrValue) : NULL)<br />
#define XML_GetAttribValueLong( pAttr )     (NULL != (pAttr) ? (LONG)strtol(BSTR_C((pAttr)-&gt;m_pbstrValue), NULL, 0) : (0L))<br />
#define XML_GetAttribValueInt( pAttr )      (NULL != (pAttr) ? (int)strtol(BSTR_C((pAttr)-&gt;m_pbstrValue), NULL, 0) : (0))</p>
<p>#endif</p>
<p>//////////////////////////////<br />
// Function prototypes</p>
<p>#if defined(__cplusplus)<br />
extern &#8220;C&#8221; {<br />
#endif</p>
<p>size_t      strlen_when( LPCSTR lpszStr, CHAR ch );<br />
size_t        strlen_notin( LPCSTR lpszStr, LPCSTR lpszSet );<br />
LPCSTR        strchr_notin( LPCSTR lpszStr, LPCSTR lpszSet );<br />
LPCSTR        strchr_skipws( LPCSTR lpszStr );</p>
<p>LPBSTRING   AllocBString( LPCSTR lpszStr, LONG lLen );</p>
<p>XMLERR      XML_OpenDocument( LPXMLDOCUMENT pDoc, LPCSTR lpszFileName, DWORD dwReserve );<br />
XMLERR      XML_CloseDocument( LPXMLDOCUMENT pDoc );<br />
LPXMLNODE    XML_GetNode( LPXMLDOCUMENT pDoc, LPXMLNODE pStartPoint, LPCSTR lpszTag, LONG lLen );<br />
LPXMLATTRIB    XML_GetNodeAttrib( LPXMLNODE pNode, LPCSTR lpszAttr, LONG lLen );<br />
LPXMLNODE    XML_GetNodeSibling( LPXMLNODE pNode, LPCSTR lpszTag, LONG lLen, BOOL IncludeThis );<br />
LONG         XML_ForEachNode( LPXMLDOCUMENT pDoc, LPXMLNODE pStartPoint, LPFNNODEPROC pfnNodeProc, LPVOID pvParam );</p>
<p>#if defined(__cplusplus)<br />
}   // extern &#8220;C&#8221; {<br />
#endif</p>
<p>#endif // #ifndef __XMLPARSE_H</p>
<h3>PLX_XMLParser.c</h3>
<p>#include &lt;assert.h&gt;<br />
#include &lt;fcntl.h&gt;<br />
#include &lt;io.h&gt;<br />
#if defined(<a href="http://www.donevii.com/post/tag/debug" class="st_tag internal_tag" rel="tag" title="Posts tagged with debug">DEBUG</a>) || defined(_<a href="http://www.donevii.com/post/tag/debug" class="st_tag internal_tag" rel="tag" title="Posts tagged with debug">DEBUG</a>)<br />
#include &lt;stdio.h&gt;<br />
#endif</p>
<p>#include &#8220;XMLParse.h&#8221;</p>
<p>//#pragma warning(disable:4305)</p>
<p>//////////////////////////////<br />
// Configure</p>
<p>//#define  USE_MEMORY_HEAP</p>
<p>#ifdef  USE_FILEBUFFER  // Whether use file system with os-layer buffer</p>
<p>#define INVALID_FILE_HANDLE         ((int)-1)<br />
#define FILE_HANDLE                 int</p>
<p>#define MODE_RDONLY                 (O_RDONLY)<br />
#define FILE_OPEN(pszFile,mode)     open( pszFile, mode )<br />
#define FILE_READ(hFile,pbuf,size)  read(hFile, (LPVOID)pbuf, size)<br />
#define FILE_SEEK(hFile,off,pos)    lseek( hFile, off, pos )<br />
#define FILE_CLOSE(hFile)           close( hFile )</p>
<p>#else</p>
<p>#define INVALID_FILE_HANDLE         ((FILE *)NULL)<br />
#define FILE_HANDLE                 FILE *</p>
<p>#define MODE_RDONLY                 (&#8220;r&#8221;)<br />
#define FILE_OPEN(pszFile,mode)     fopen( pszFile, mode )<br />
#define FILE_READ(hFile,pbuf,size)  fread((LPVOID)pbuf, size, 1, hFile)<br />
#define FILE_SEEK(hFile,off,pos)    fseek( hFile, off, pos )<br />
#define FILE_CLOSE(hFile)           fclose( hFile )</p>
<p>#endif</p>
<p>//////////////////////////////<br />
// Constants</p>
<p>enum {    MAXLEN_READBUF    = 1024 };</p>
<p>typedef enum {<br />
PSTAT_STOP      = 0&#215;0,<br />
PSTAT_INITIAL,<br />
PSTAT_FINAL,<br />
PSTAT_DECL_BEG,<br />
PSTAT_DECL_END,<br />
PSTAT_ELEM_BEG,<br />
PSTAT_ELEM_END,<br />
PSTAT_TEXT_BEG,<br />
PSTAT_TEXT_END,<br />
PSTAT_CDATA_BEG,<br />
PSTAT_CDATA_END,<br />
PSTAT_COMM_BEG,<br />
PSTAT_COMM_END,<br />
PSTAT_ERROR,<br />
} PARSESTAT;</p>
<p>//////////////////////////////<br />
// Macros</p>
<p>#define ZERO_MEMORY(p, size) \<br />
( memset((LPVOID)(p), 0&#215;0, (size_t)size) )</p>
<p>#define is_WhiteSpace(ch)   (((ch) == &#8216; &#8216;  || (ch) == &#8216;\t&#8217;) ? TRUE : FALSE)<br />
#define is_LineBreak(ch)    (((ch) == &#8216;\r&#8217; || (ch) == &#8216;\n&#8217;) ? TRUE : FALSE)<br />
#define is_LeftBracket(ch)    ((ch) == &#8216;&lt;&#8217; ? TRUE : FALSE)<br />
#define is_RightBracket(ch)    ((ch) == &#8216;&gt;&#8217; ? TRUE : FALSE)</p>
<p>#define is_BufferEmpty(ps)  ((ps)-&gt;m_lReadCursor &gt;= (ps)-&gt;m_lReadSize ? TRUE : FALSE)<br />
#define get_BufferChar(ps)  ((CHAR)((ps)-&gt;m_aReadBuf[(ps)-&gt;m_lReadCursor]))</p>
<p>#define is_FirstChild(pn)    ((pn)-&gt;m_pPrevSibling == NULL ? TRUE : FALSE)<br />
#define is_LastChild(pn)    ((pn)-&gt;m_pNextSibling == NULL ? TRUE : FALSE)</p>
<p>//////////////////////////////<br />
// Structures</p>
<p>struct tagXMLParseStat<br />
{<br />
PARSESTAT   m_eParseStat;<br />
LONG        m_lDepth;<br />
LPXMLNODE    m_pRootNode;<br />
LPXMLNODE    m_pLastNode;</p>
<p>FILE_HANDLE    m_hOpenFile;<br />
LONG        m_lFileCursor;<br />
LONG        m_lFileLength;</p>
<p>LONG        m_lLineNo;<br />
LONG        m_lReadCursor;<br />
LONG        m_lReadSize;<br />
BYTE        m_aReadBuf[MAXLEN_READBUF];<br />
};<br />
typedef struct tagXMLParseStat            XMLPARSESTAT;<br />
typedef struct tagXMLParseStat            *LPXMLPARSESTAT;<br />
typedef struct tagXMLParseStat    const    *LPCXMLPARSESTAT;</p>
<p>struct tagXMLIterator<br />
{<br />
LONG            m_lCount;<br />
LPFNNODEPROC    m_pfnProc;<br />
LPVOID          m_pvParam;<br />
LPXMLNODE       m_pStation;<br />
};<br />
typedef struct tagXMLIterator       XMLITERFATOR;<br />
typedef struct tagXMLIterator       *LPXMLITERFATOR;<br />
typedef struct tagXMLIterator const *LPCXMLITERFATOR;</p>
<p>/*struct tagMemoryPage<br />
{<br />
LONG    lGranu ;<br />
LONG    lSize;<br />
LPVOID  pvPage;<br />
BYTE    bUseFlags[1];<br />
};<br />
typedef struct tagMemoryPage        MEMORYPAGE;<br />
typedef struct tagMemoryPage        *LPMEMORYPAGE;<br />
typedef struct tagMemoryPage const  *LPCMEMORYPAGE;*/</p>
<p>//////////////////////////////<br />
// Function prototypes</p>
<p>#if defined(__cplusplus)<br />
extern &#8220;C&#8221; {<br />
#endif</p>
<p>static void        XML_FreeNodeTree( LPXMLNODE pNode );<br />
static void        XML_FreeAttribList( LPXMLATTRIB pAttrib );<br />
static void     XML_IterateTree( LPXMLNODE pTree, LPXMLITERFATOR pIterator );<br />
static BOOL     XMLCmpNode_EqualTag( LPCXMLNODE pNode, LPVOID pvParam );</p>
<p>static BOOL        Parser_RoutineStart( LPXMLPARSESTAT pParseStat, LPXMLDOCUMENT pResult );<br />
static int        Parser_GetTagString( LPXMLPARSESTAT pParseStat, LPSTR lpszBuf );<br />
static BOOL        Parser_ReadStream( LPXMLPARSESTAT pParseStat );<br />
static void        Parser_OnInitial( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static void        Parser_OnElemBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static void        Parser_OnElemEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static void        Parser_OnTextBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static void        Parser_OnTextEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static void        Parser_OnCDATABegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static void        Parser_OnCDATAEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static void        Parser_OnCommBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static void        Parser_OnCommEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static void        Parser_OnDeclBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static void        Parser_OnDeclEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag );<br />
static BOOL        Parser_OnFinal( LPXMLPARSESTAT pParseStat );<br />
static BOOL        Parser_OnError( LPXMLPARSESTAT pParseStat );</p>
<p>//#if defined(USE_MEMORY_HEAP)<br />
//static LPVOID   MemoryHeap_Create( LONG lInitialGranu, LONG lInitialSize );<br />
//static BOOL     MemoryHeap_Destroy( LPVOID );<br />
//static LPVOID   MemoryHeap_Alloc( void );<br />
//static void     MemoryHeap_Free( LPVOID pvBlock );<br />
//#endif</p>
<p>#if defined(__cplusplus)<br />
}   // extern &#8220;C&#8221; {<br />
#endif</p>
<p>//////////////////////////////<br />
// Function implementations</p>
<p>#if defined(__cplusplus)<br />
extern &#8220;C&#8221; {<br />
#endif</p>
<p>/*********************************************************************\<br />
* Function: strlen_when<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
size_t strlen_when( LPCSTR lpszStr, CHAR ch )<br />
{<br />
register size_t nLen;<br />
assert( NULL != lpszStr );<br />
for ( nLen = 0; *lpszStr != ch &amp;&amp; *lpszStr != &#8216;\0&#8242;;    lpszStr++, nLen++ )<br />
;<br />
return nLen;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: strlen_notin<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
size_t strlen_notin( LPCSTR lpszStr, LPCSTR lpszSet )<br />
{<br />
register size_t nLen;<br />
assert( NULL != lpszStr );<br />
for ( nLen = 0; *lpszStr != &#8216;\0&#8242; &amp;&amp; NULL == strchr(lpszSet, *lpszStr); lpszStr++, nLen++ )<br />
;<br />
return nLen;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: strchr_notin<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
LPCSTR strchr_notin( LPCSTR lpszStr, LPCSTR lpszSet )<br />
{<br />
assert( NULL != lpszStr );<br />
for ( ; *lpszStr != &#8216;\0&#8242; &amp;&amp; NULL == strchr(lpszSet, *lpszStr); lpszStr++ )<br />
;<br />
return lpszStr;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: strchr_skipws<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
LPCSTR strchr_skipws( LPCSTR lpszStr )<br />
{<br />
assert( NULL != lpszStr );<br />
for ( ; *lpszStr != &#8216;\0&#8242; &amp;&amp; is_WhiteSpace(*lpszStr); lpszStr++ )<br />
;<br />
return lpszStr;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: AllocBString<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
LPBSTRING AllocBString( LPCSTR lpszStr, LONG lLen )<br />
{<br />
LPBSTRING pBStr = (LPBSTRING)malloc( sizeof(LONG) + lLen + 1 );<br />
assert( NULL != pBStr );</p>
<p>pBStr-&gt;m_lLength = lLen;<br />
strncpy( &amp;pBStr-&gt;m_paStr[0], lpszStr, lLen );<br />
pBStr-&gt;m_paStr[lLen] = &#8216;\0&#8242;;</p>
<p>return pBStr;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: XML_OpenDocument<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
XMLERR XML_OpenDocument( LPXMLDOCUMENT pDoc, LPCSTR lpszFileName, DWORD dwReserve )<br />
{<br />
BOOL            bRet;<br />
FILE_HANDLE        hFile;<br />
XMLPARSESTAT    xmlParseStat;</p>
<p>assert( NULL != pDoc );<br />
assert( NULL != lpszFileName );</p>
<p>if ( pDoc-&gt;m_eDocStat == DSTAT_OPENED )<br />
return XMLERR_ALRDOPEN;</p>
<p>ZERO_MEMORY( &amp;xmlParseStat, sizeof(XMLPARSESTAT) );</p>
<p>hFile = FILE_OPEN( lpszFileName, MODE_RDONLY );<br />
if ( INVALID_FILE_HANDLE == hFile )<br />
return XMLERR_EFILE;</p>
<p>xmlParseStat.m_hOpenFile    = hFile;<br />
xmlParseStat.m_lFileCursor    = 0;<br />
xmlParseStat.m_lFileLength    = FILE_SEEK( hFile, 0, SEEK_END );<br />
FILE_SEEK( hFile, 0, SEEK_SET );</p>
<p>xmlParseStat.m_lDepth = 0;<br />
xmlParseStat.m_lLineNo = 1;<br />
bRet = Parser_RoutineStart( &amp;xmlParseStat, pDoc );<br />
if ( FALSE == bRet )<br />
{<br />
FILE_CLOSE( hFile );<br />
return XMLERR_EPARSE;<br />
}</p>
<p>pDoc-&gt;m_eDocStat    = DSTAT_OPENED;<br />
pDoc-&gt;m_lpRootNode    = xmlParseStat.m_pRootNode;<br />
FILE_CLOSE( hFile );<br />
return XMLERR_OK;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: XML_CloseDocument<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
XMLERR XML_CloseDocument( LPXMLDOCUMENT pDoc )<br />
{<br />
if ( NULL != pDoc &amp;&amp; pDoc-&gt;m_eDocStat == DSTAT_OPENED )<br />
{<br />
XML_FreeNodeTree( pDoc-&gt;m_lpRootNode );<br />
pDoc-&gt;m_lpRootNode = NULL;<br />
pDoc-&gt;m_eDocStat = DSTAT_UNOPEN;<br />
}<br />
return XMLERR_OK;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_GetTagString<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
int Parser_GetTagString( LPXMLPARSESTAT pParseStat, LPSTR lpszBuf )<br />
{<br />
int        nLen;<br />
CHAR    ch;<br />
CHAR    chTerm;<br />
BOOL    bInclude;</p>
<p>// Should to ensure barket match Here!</p>
<p>nLen = 0;<br />
for ( ;; )<br />
{<br />
if ( is_BufferEmpty(pParseStat) &amp;&amp; FALSE == Parser_ReadStream(pParseStat) )<br />
goto __RET;</p>
<p>ch = get_BufferChar(pParseStat);<br />
if ( ch == &#8216;\n&#8217; )<br />
pParseStat-&gt;m_lLineNo++;</p>
<p>if ( !is_WhiteSpace(ch) &amp;&amp; !is_LineBreak(ch) )<br />
break;</p>
<p>pParseStat-&gt;m_lReadCursor++;<br />
}</p>
<p>if ( is_LeftBracket(ch) )<br />
{<br />
chTerm = &#8216;&gt;&#8217;;<br />
bInclude = TRUE;<br />
}<br />
else<br />
{<br />
chTerm = &#8216;&lt;&#8217;;<br />
bInclude = FALSE;<br />
}</p>
<p>for ( ;; )<br />
{<br />
if ( is_BufferEmpty(pParseStat) &amp;&amp; FALSE == Parser_ReadStream(pParseStat) )<br />
break;</p>
<p>ch = get_BufferChar(pParseStat);<br />
if ( ch == &#8216;\n&#8217; )<br />
pParseStat-&gt;m_lLineNo++;</p>
<p>if ( ch == chTerm )<br />
{<br />
if ( FALSE != bInclude )<br />
{<br />
lpszBuf[nLen++] = chTerm;<br />
pParseStat-&gt;m_lReadCursor++;<br />
}<br />
break;<br />
}</p>
<p>lpszBuf[nLen++] = ch;<br />
pParseStat-&gt;m_lReadCursor++;<br />
}</p>
<p>__RET:<br />
lpszBuf[nLen] = &#8216;\0&#8242;;<br />
return nLen;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_ReadStream<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
BOOL Parser_ReadStream( LPXMLPARSESTAT pParseStat )<br />
{<br />
size_t    nSize;</p>
<p>pParseStat-&gt;m_lReadCursor    = 0;<br />
pParseStat-&gt;m_lReadSize    = 0;<br />
nSize = FILE_READ( pParseStat-&gt;m_hOpenFile, (LPVOID)&amp;pParseStat-&gt;m_aReadBuf[0], MAXLEN_READBUF );<br />
if ( nSize &lt;= 0 )<br />
return FALSE;</p>
<p>pParseStat-&gt;m_lReadSize        = (LONG)nSize;<br />
pParseStat-&gt;m_lFileCursor  += (LONG)nSize;<br />
return TRUE;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_RoutineStart<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
BOOL Parser_RoutineStart( LPXMLPARSESTAT pParseStat, LPXMLDOCUMENT pResult )<br />
{<br />
BOOL    bRet;<br />
CHAR    szTag[256];</p>
<p>assert( NULL != pParseStat );</p>
<p>pParseStat-&gt;m_eParseStat = PSTAT_INITIAL;<br />
while ( pParseStat-&gt;m_eParseStat != PSTAT_STOP )<br />
{<br />
switch ( pParseStat-&gt;m_eParseStat )<br />
{<br />
case PSTAT_INITIAL:     Parser_OnInitial( pParseStat, &amp;szTag[0] );        break;</p>
<p>case PSTAT_DECL_BEG:    Parser_OnDeclBegin( pParseStat, &amp;szTag[0] );    break;<br />
case PSTAT_DECL_END:    Parser_OnDeclEnd( pParseStat, &amp;szTag[0] );        break;</p>
<p>case PSTAT_ELEM_BEG:    Parser_OnElemBegin( pParseStat, &amp;szTag[0] );    break;<br />
case PSTAT_ELEM_END:    Parser_OnElemEnd( pParseStat, &amp;szTag[0] );      break;</p>
<p>case PSTAT_TEXT_BEG:    Parser_OnTextBegin( pParseStat, &amp;szTag[0] );    break;<br />
case PSTAT_TEXT_END:    Parser_OnTextEnd( pParseStat, &amp;szTag[0] );        break;</p>
<p>case PSTAT_CDATA_BEG:    Parser_OnCDATABegin( pParseStat, &amp;szTag[0] );    break;<br />
case PSTAT_CDATA_END:    Parser_OnCDATAEnd( pParseStat, &amp;szTag[0] );        break;</p>
<p>case PSTAT_COMM_BEG:    Parser_OnCommBegin( pParseStat, &amp;szTag[0] );    break;<br />
case PSTAT_COMM_END:    Parser_OnCommEnd( pParseStat, &amp;szTag[0] );        break;</p>
<p>case PSTAT_FINAL:        bRet = Parser_OnFinal( pParseStat );            break;<br />
case PSTAT_ERROR:        bRet = Parser_OnError( pParseStat );            break;</p>
<p>default:<br />
assert( !&#8221;Unknown parsing status!&#8221; );<br />
break;<br />
}<br />
}<br />
return bRet;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnInitial<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnInitial( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
int     nLen;<br />
assert( NULL != lpszTag );</p>
<p>lpszTag[0] = &#8216;\0&#8242;;</p>
<p>nLen = Parser_GetTagString( pParseStat, lpszTag );<br />
if ( nLen &lt;= 0 )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_STOP;<br />
return;<br />
}</p>
<p>if ( lpszTag[0] == &#8216;&lt;&#8217;  )<br />
{<br />
if ( lpszTag[1] == &#8216;?&#8217;)<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_DECL_BEG;<br />
}<br />
else if ( !strncmp(&amp;lpszTag[1], &#8220;!&#8211;&#8221;, 3) )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_COMM_BEG;<br />
}<br />
else if ( lpszTag[1] == &#8216;/&#8217; )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_ELEM_END;<br />
}<br />
else if ( isalpha(lpszTag[1]) )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_ELEM_BEG;<br />
}<br />
else if ( !strncmp(&amp;lpszTag[1], &#8220;![CDATA[", 8) )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_CDATA_BEG;<br />
}<br />
else<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_ERROR;<br />
}<br />
}<br />
else if ( NULL != pParseStat-&gt;m_pLastNode )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_TEXT_BEG;<br />
}<br />
else<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_ERROR;<br />
}<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnFinal<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
BOOL Parser_OnFinal( LPXMLPARSESTAT pParseStat )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_STOP;<br />
return TRUE;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnError<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
BOOL Parser_OnError( LPXMLPARSESTAT pParseStat )<br />
{<br />
XML_FreeNodeTree( pParseStat-&gt;m_pRootNode );<br />
pParseStat-&gt;m_pRootNode     = NULL;<br />
pParseStat-&gt;m_eParseStat = PSTAT_STOP;<br />
TRACE( "[Xml Parser]: Syntax error @ %s #%ld.\n&#8221;, &#8220;&#8221;, pParseStat-&gt;m_lLineNo);<br />
return FALSE;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnDeclBegin<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnDeclBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
int nLenTag;</p>
<p>if ( NULL != pParseStat-&gt;m_pRootNode )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_ERROR;<br />
return;<br />
}</p>
<p>lpszTag = (LPSTR)strchr_skipws( (LPCSTR)(lpszTag + 2) );<br />
if ( lpszTag == &#8216;\0&#8242; )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_ERROR;<br />
return;<br />
}</p>
<p>nLenTag = (int)strlen_notin(lpszTag, &#8221; \t\r\n&gt;&#8221;);<br />
if ( nLenTag == 3 &amp;&amp; !strncmp(lpszTag, &#8220;xml&#8221;, 3) )<br />
{<br />
// Here, dispose version and coding infomation in XML document header<br />
}<br />
else if ( nLenTag == 14 &amp;&amp; !strncmp(lpszTag, &#8220;xml-stylesheet&#8221;, 3) )<br />
{<br />
// Unsupport<br />
}<br />
else<br />
{<br />
// Unknown declaretion<br />
}</p>
<p>pParseStat-&gt;m_eParseStat = PSTAT_INITIAL;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnDeclEnd<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnDeclEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
// Do noting<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnElemBegin<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnElemBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
int         nLenTag;<br />
int         nLenValue;<br />
LPSTR       lpszValue;<br />
LPXMLNODE   pNode;<br />
LPXMLATTRIB    pAttrib;<br />
LPXMLATTRIB pPrevAttr;</p>
<p>assert( is_LeftBracket(lpszTag[0]) );</p>
<p>// Multi-root node is not supproted<br />
if ( 0 == pParseStat-&gt;m_lDepth &amp;&amp; NULL != pParseStat-&gt;m_pRootNode )<br />
goto __ERROR;</p>
<p>pNode = (LPXMLNODE)malloc(sizeof(XMLNODE));<br />
if ( NULL == pNode )<br />
goto __ERROR;</p>
<p>ZERO_MEMORY( pNode, sizeof(XMLNODE) );<br />
pNode-&gt;m_eNodeType    = NODETYPE_ELEM;<br />
pNode-&gt;m_lDepth        = pParseStat-&gt;m_lDepth;<br />
if ( NULL != pParseStat-&gt;m_pLastNode )<br />
{<br />
assert( pNode-&gt;m_lDepth &gt;= pParseStat-&gt;m_pLastNode-&gt;m_lDepth );<br />
if ( pNode-&gt;m_lDepth &gt; pParseStat-&gt;m_pLastNode-&gt;m_lDepth ) // new child<br />
{<br />
pNode-&gt;m_pParent = pParseStat-&gt;m_pLastNode;<br />
pParseStat-&gt;m_pLastNode-&gt;m_pFirstChild = pNode;<br />
}<br />
else if ( pNode-&gt;m_lDepth == pParseStat-&gt;m_pLastNode-&gt;m_lDepth ) // new sibling<br />
{<br />
pNode-&gt;m_pParent = pParseStat-&gt;m_pLastNode-&gt;m_pParent;<br />
pParseStat-&gt;m_pLastNode-&gt;m_pNextSibling = pNode;<br />
pNode-&gt;m_pPrevSibling = pParseStat-&gt;m_pLastNode;<br />
}</p>
<p>if ( NULL != pNode-&gt;m_pParent )<br />
{<br />
pNode-&gt;m_pParent-&gt;m_lChildNum++;<br />
pNode-&gt;m_pParent-&gt;m_lChildNum_Elem++;<br />
}<br />
}</p>
<p>if ( NULL == pParseStat-&gt;m_pRootNode )<br />
{<br />
pParseStat-&gt;m_pRootNode = pNode;<br />
}<br />
pNode-&gt;m_pRoot = pParseStat-&gt;m_pRootNode;</p>
<p>pParseStat-&gt;m_pLastNode    = pNode;</p>
<p>lpszTag++;<br />
nLenTag = (int)strlen_notin(lpszTag, &#8221; \t\r\n&gt;&#8221;);<br />
if ( nLenTag &lt;= 0 )<br />
goto __ERROR;</p>
<p>pNode-&gt;m_pbstrTag = BSTR_ALLOCEX(lpszTag, nLenTag);<br />
if ( NULL == pNode-&gt;m_pbstrTag )<br />
goto __ERROR;</p>
<p>lpszTag = (LPSTR)(lpszTag + nLenTag);</p>
<p>for ( pPrevAttr = NULL;; )<br />
{<br />
lpszTag = (LPSTR)strchr_skipws( lpszTag );</p>
<p>if ( is_RightBracket(*lpszTag) )<br />
{<br />
pParseStat-&gt;m_lDepth++; // Move down one layer<br />
pParseStat-&gt;m_eParseStat = PSTAT_INITIAL;<br />
break;<br />
}<br />
else if ( !strncmp(lpszTag, &#8220;/&gt;&#8221;, 2) )<br />
{<br />
//pParseStat-&gt;m_lDepth&#8211;; //<br />
pParseStat-&gt;m_eParseStat = PSTAT_INITIAL;<br />
break;<br />
}</p>
<p>nLenTag = (int)strlen_when( lpszTag, &#8216;=&#8217; );<br />
if ( nLenTag &lt;= 0 )<br />
goto __ERROR;</p>
<p>lpszValue = strchr( (LPCSTR)(lpszTag + nLenTag), &#8216;\&#8221;&#8216; );<br />
if ( NULL == lpszValue )<br />
goto __ERROR;</p>
<p>lpszValue++;<br />
nLenValue = (int)strlen_when( lpszValue, &#8216;\&#8221;&#8216; );</p>
<p>//if ( nLenValue &lt;= 0 )<br />
//    goto __ERROR;</p>
<p>pAttrib = (LPXMLATTRIB)malloc(sizeof(XMLATTRIB));<br />
if ( NULL == pAttrib )<br />
goto __ERROR;<br />
ZERO_MEMORY( pAttrib, sizeof(XMLATTRIB) );</p>
<p>pAttrib-&gt;m_pbstrName    = BSTR_ALLOCEX( lpszTag, nLenTag );<br />
pAttrib-&gt;m_pbstrValue    = BSTR_ALLOCEX( lpszValue, nLenValue );<br />
if ( NULL == pAttrib-&gt;m_pbstrName || NULL == pAttrib-&gt;m_pbstrValue )<br />
goto __ERROR;</p>
<p>if ( NULL == pNode-&gt;m_pFirstAttrib )<br />
pNode-&gt;m_pFirstAttrib = pAttrib;</p>
<p>if ( NULL != pPrevAttr )<br />
pPrevAttr-&gt;m_pNext = pAttrib;<br />
pPrevAttr = pAttrib;</p>
<p>pNode-&gt;m_lAttribNum++;<br />
lpszTag = lpszValue + nLenValue + 1;<br />
}</p>
<p>return;</p>
<p>__ERROR:<br />
XML_FreeNodeTree( pNode );<br />
pParseStat-&gt;m_eParseStat = PSTAT_ERROR;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnElemEnd<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnElemEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
pParseStat-&gt;m_lDepth&#8211;;</p>
<p>if ( NULL != pParseStat-&gt;m_pLastNode )<br />
{<br />
if ( NULL != pParseStat-&gt;m_pLastNode-&gt;m_pParent )<br />
pParseStat-&gt;m_pLastNode-&gt;m_pParent-&gt;m_pLastChild = pParseStat-&gt;m_pLastNode;</p>
<p>if ( pParseStat-&gt;m_pLastNode-&gt;m_lDepth &gt; pParseStat-&gt;m_lDepth )<br />
pParseStat-&gt;m_pLastNode = pParseStat-&gt;m_pLastNode-&gt;m_pParent;<br />
}</p>
<p>if ( 0 == pParseStat-&gt;m_lDepth )<br />
pParseStat-&gt;m_eParseStat = PSTAT_FINAL;<br />
else<br />
pParseStat-&gt;m_eParseStat = PSTAT_INITIAL;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnTextBegin<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnTextBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
LPXMLNODE pNode;</p>
<p>pNode = (LPXMLNODE)malloc(sizeof(XMLNODE));<br />
if ( NULL == pParseStat-&gt;m_pLastNode )<br />
goto __ERROR;</p>
<p>ZERO_MEMORY( pNode, sizeof(XMLNODE) );<br />
pNode-&gt;m_eNodeType    = NODETYPE_TEXT;<br />
pNode-&gt;m_lDepth        = pParseStat-&gt;m_lDepth;</p>
<p>if ( NULL != pParseStat-&gt;m_pLastNode )<br />
{<br />
assert( pNode-&gt;m_lDepth &gt;= pParseStat-&gt;m_pLastNode-&gt;m_lDepth );<br />
if ( pNode-&gt;m_lDepth &gt; pParseStat-&gt;m_pLastNode-&gt;m_lDepth )<br />
{<br />
pNode-&gt;m_pParent = pParseStat-&gt;m_pLastNode;<br />
pParseStat-&gt;m_pLastNode-&gt;m_pFirstChild = pNode;<br />
}<br />
else if ( pNode-&gt;m_lDepth == pParseStat-&gt;m_pLastNode-&gt;m_lDepth )<br />
{<br />
pNode-&gt;m_pParent = pParseStat-&gt;m_pLastNode-&gt;m_pParent;<br />
pParseStat-&gt;m_pLastNode-&gt;m_pNextSibling = pNode;<br />
pNode-&gt;m_pPrevSibling = pParseStat-&gt;m_pLastNode;<br />
}</p>
<p>if ( NULL != pNode-&gt;m_pParent )<br />
pNode-&gt;m_pParent-&gt;m_lChildNum++;</p>
<p>pNode-&gt;m_pRoot = pParseStat-&gt;m_pLastNode-&gt;m_pRoot;<br />
}</p>
<p>pParseStat-&gt;m_pLastNode    = pNode;</p>
<p>pNode-&gt;m_pbstrTag = BSTR_ALLOC(lpszTag);<br />
if ( NULL == pNode-&gt;m_pbstrTag )<br />
goto __ERROR;</p>
<p>pParseStat-&gt;m_lDepth++; // Move down one layer<br />
pParseStat-&gt;m_eParseStat = PSTAT_TEXT_END;<br />
return;</p>
<p>__ERROR:<br />
XML_FreeNodeTree( pNode );<br />
pParseStat-&gt;m_eParseStat = PSTAT_ERROR;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnTextEnd<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnTextEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
// Move up one layer<br />
pParseStat-&gt;m_lDepth&#8211;;</p>
<p>if ( NULL != pParseStat-&gt;m_pLastNode &amp;&amp;<br />
pParseStat-&gt;m_pLastNode-&gt;m_lDepth &gt; pParseStat-&gt;m_lDepth )<br />
pParseStat-&gt;m_pLastNode = pParseStat-&gt;m_pLastNode-&gt;m_pParent;</p>
<p>pParseStat-&gt;m_eParseStat = PSTAT_INITIAL;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnCommBegin<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnCommBegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_INITIAL;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnCommEnd<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnCommEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnCDATABegin<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnCDATABegin( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
pParseStat-&gt;m_eParseStat = PSTAT_INITIAL;<br />
// Should convert to text here<br />
}</p>
<p>/*********************************************************************\<br />
* Function: Parser_OnCDATAEnd<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void Parser_OnCDATAEnd( LPXMLPARSESTAT pParseStat, LPSTR lpszTag )<br />
{<br />
}</p>
<p>/*********************************************************************\<br />
* Function: XML_IterateTree<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void XML_IterateTree( LPXMLNODE pTree, LPXMLITERFATOR pIterator )<br />
{<br />
register ITERSTAT eStat;<br />
if ( NULL != pTree )<br />
{<br />
pIterator-&gt;m_pStation = pTree;<br />
eStat = pIterator-&gt;m_pfnProc( pTree, pIterator-&gt;m_pvParam );<br />
if ( eStat == ISTAT_STOP )<br />
return;<br />
if ( eStat != ISTAT_PASS )<br />
pIterator-&gt;m_lCount++;</p>
<p>XML_IterateTree( pTree-&gt;m_pFirstChild, pIterator );<br />
XML_IterateTree( pTree-&gt;m_pNextSibling, pIterator );<br />
}<br />
}</p>
<p>/*********************************************************************\<br />
* Function: XML_ForEachNode<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
LONG XML_ForEachNode( LPXMLDOCUMENT pDoc, LPXMLNODE pStartPoint, LPFNNODEPROC pfnNodeProc, LPVOID pvParam )<br />
{<br />
XMLITERFATOR    iter;</p>
<p>assert( NULL != pDoc );<br />
assert( NULL != pfnNodeProc );</p>
<p>if ( pDoc-&gt;m_eDocStat == DSTAT_UNOPEN || (NULL != pStartPoint &amp;&amp; pStartPoint-&gt;m_pRoot != pDoc-&gt;m_lpRootNode) )<br />
return 0;</p>
<p>iter.m_lCount   = 0;<br />
iter.m_pStation = NULL;<br />
iter.m_pvParam  = pvParam;<br />
iter.m_pfnProc  = pfnNodeProc;</p>
<p>pStartPoint = (NULL == pStartPoint ? pDoc-&gt;m_lpRootNode : pStartPoint);<br />
XML_IterateTree( pStartPoint, &amp;iter );<br />
return iter.m_lCount;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: XMLCmpNode_EqualTag<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
ITERSTAT XMLCmpNode_EqualTag( LPCXMLNODE pNode, LPVOID pvParam )<br />
{<br />
if ( FALSE != BSTR_EQUAL(pNode-&gt;m_pbstrTag, BSTR_CAST(pvParam)) )<br />
return ISTAT_STOP;<br />
else<br />
return ISTAT_CONTINUE;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: XML_GetNode<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
LPXMLNODE XML_GetNode( LPXMLDOCUMENT pDoc, LPXMLNODE pStartPoint, LPCSTR lpszTag, LONG lLen )<br />
{<br />
BSTRING         bStr;<br />
XMLITERFATOR    iter;</p>
<p>assert( NULL != lpszTag );<br />
assert( NULL != pDoc );</p>
<p>if ( pDoc-&gt;m_eDocStat == DSTAT_UNOPEN || pStartPoint-&gt;m_pRoot != pDoc-&gt;m_lpRootNode )<br />
return NULL;</p>
<p>bStr.m_lLength  = lLen;<br />
bStr.m_pszStr   = lpszTag;</p>
<p>iter.m_lCount   = 0;<br />
iter.m_pfnProc  = &amp;XMLCmpNode_EqualTag;<br />
iter.m_pStation = NULL;<br />
iter.m_pvParam  = (LPVOID)&amp;bStr;</p>
<p>pStartPoint = (NULL == pStartPoint ? pDoc-&gt;m_lpRootNode : pStartPoint);<br />
XML_IterateTree( pStartPoint, &amp;iter );<br />
return (iter.m_pStation);<br />
}</p>
<p>/*********************************************************************\<br />
* Function: XML_GetNodeAttrib<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
LPXMLATTRIB    XML_GetNodeAttrib( LPXMLNODE pNode, LPCSTR lpszAttr, LONG lLen )<br />
{<br />
BSTRING     bStr;<br />
LPXMLATTRIB pAttrib;</p>
<p>assert( NULL != lpszAttr );<br />
assert( NULL != pNode );<br />
bStr.m_lLength  = lLen;<br />
bStr.m_pszStr   = lpszAttr;</p>
<p>for ( pAttrib = XML_GetNodeFirstAttrib(pNode); NULL != pAttrib; pAttrib = XML_GetNodeNextAttrib(pAttrib) )<br />
{<br />
if ( FALSE != BSTR_EQUAL(pAttrib-&gt;m_pbstrName, &amp;bStr) )<br />
break;<br />
}</p>
<p>return pAttrib;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: XML_GetNodeSibling<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
LPXMLNODE XML_GetNodeSibling( LPXMLNODE pNode, LPCSTR lpszTag, LONG lLen, BOOL bIncludeThis )<br />
{<br />
BSTRING     bStr;</p>
<p>assert( NULL != lpszTag );<br />
assert( NULL != pNode );<br />
bStr.m_lLength  = lLen;<br />
bStr.m_pszStr   = lpszTag;</p>
<p>if ( FALSE != bIncludeThis &amp;&amp; FALSE != BSTR_EQUAL(pNode-&gt;m_pbstrTag, &amp;bStr) )<br />
return pNode;</p>
<p>for ( pNode = XML_GetNodeNextSibling(pNode); NULL != pNode; pNode = XML_GetNodeNextSibling(pNode) )<br />
{<br />
if ( FALSE != BSTR_EQUAL(pNode-&gt;m_pbstrTag, &amp;bStr) )<br />
break;<br />
}</p>
<p>return pNode;<br />
}</p>
<p>/*********************************************************************\<br />
* Function: XML_FreeNodeTree<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void XML_FreeNodeTree( LPXMLNODE pNode )<br />
{<br />
if ( NULL != pNode )<br />
{<br />
BSTR_FREE( pNode-&gt;m_pbstrTag );</p>
<p>XML_FreeAttribList( pNode-&gt;m_pFirstAttrib );</p>
<p>if ( is_FirstChild(pNode) &amp;&amp; NULL != pNode-&gt;m_pParent )<br />
pNode-&gt;m_pParent-&gt;m_pFirstChild = pNode-&gt;m_pNextSibling;</p>
<p>if ( NULL != pNode-&gt;m_pNextSibling )<br />
pNode-&gt;m_pNextSibling-&gt;m_pPrevSibling = pNode-&gt;m_pPrevSibling;<br />
if ( NULL != pNode-&gt;m_pPrevSibling )<br />
pNode-&gt;m_pPrevSibling-&gt;m_pNextSibling = pNode-&gt;m_pNextSibling;</p>
<p>XML_FreeNodeTree( pNode-&gt;m_pFirstChild );<br />
XML_FreeNodeTree( pNode-&gt;m_pNextSibling );</p>
<p>free( pNode );<br />
}<br />
}</p>
<p>/*********************************************************************\<br />
* Function: XML_FreeAttribList<br />
* Purpose:<br />
* Params:<br />
* Return<br />
* Remarks<br />
**********************************************************************/<br />
void XML_FreeAttribList( LPXMLATTRIB pAttrib )<br />
{<br />
LPXMLATTRIB pNext;</p>
<p>while ( NULL != pAttrib )<br />
{<br />
pNext = pAttrib-&gt;m_pNext;<br />
BSTR_FREE( pAttrib-&gt;m_pbstrName );<br />
BSTR_FREE( pAttrib-&gt;m_pbstrValue );<br />
free( pAttrib );<br />
pAttrib = pNext;<br />
}<br />
}</p>
<p>#if defined(__cplusplus)<br />
}   // extern &#8220;C&#8221; {<br />
#endif</p>
]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/353.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XML 生成类</title>
		<link>http://www.donevii.com/post/14.html</link>
		<comments>http://www.donevii.com/post/14.html#comments</comments>
		<pubDate>Thu, 17 Aug 2006 07:18:52 +0000</pubDate>
		<dc:creator>dengwei</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[class]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[ror]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[扩展]]></category>
		<category><![CDATA[类]]></category>
		<category><![CDATA[需求]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=14</guid>
		<description><![CDATA[因为时常用到 XML ，但是有时是在 PHP4 环境、有时是在 PHP5 环境，并且有的环境中并没有编译 XML 的扩展，所以没办法，为了让代码可以在任意环境运行，只好自己写了生成 XML 的类，现在的功... ]]></description>
			<content:encoded><![CDATA[<p>因为时常用到 <a href="http://www.donevii.com/post/tag/xml" class="st_tag internal_tag" rel="tag" title="Posts tagged with xml">XML</a> ，但是有时是在 <a href="http://www.donevii.com/post/tag/php" class="st_tag internal_tag" rel="tag" title="Posts tagged with php">PHP</a>4 环境、有时是在 <a href="http://www.donevii.com/post/tag/php" class="st_tag internal_tag" rel="tag" title="Posts tagged with php">PHP</a>5 环境，并且有的环境中并没有编译 <a href="http://www.donevii.com/post/tag/xml" class="st_tag internal_tag" rel="tag" title="Posts tagged with xml">XML</a> 的扩展，所以没办法，为了让代码可以在任意环境运行，只好自己写了生成 <a href="http://www.donevii.com/post/tag/xml" class="st_tag internal_tag" rel="tag" title="Posts tagged with xml">XML</a> 的类，现在的功能仅支持生成 <a href="http://www.donevii.com/post/tag/xml" class="st_tag internal_tag" rel="tag" title="Posts tagged with xml">XML</a> 没有读取，暂时已经能较好的完成我的需求了，过段时间考虑重写一下，现在的代码 looks like too bad.</p>
<p>:)</p>
<p>使用时请把 <a href="http://www.donevii.com/post/tag/debug" class="st_tag internal_tag" rel="tag" title="Posts tagged with debug">DEBUG</a> 部分代码给注释掉。</p>
<p style="border: 1px solid #333333; padding: 1em; background-color: #eeeeee; font-size: 12px">&lt;?php<br />
/*<br />
* $Id$<br />
*/</p>
<p>// 程序名：xml.php<br />
// 用  途：根据传入内容生成 XML 文件<br />
// 作  者：邓威<br />
// 日  期：2006-03-04<br />
// 修　改：2006-03-13 邓威，错误修正<br />
// 修　改：2006-07-07 邓威，重写代码，把原先的三个 <a href="http://www.donevii.com/post/tag/class" class="st_tag internal_tag" rel="tag" title="Posts tagged with class">class</a> 改写成一个<br />
error_reporting(E_ALL);</p>
<p>/* 例子一 */<br />
$tree = new xml(&#8220;tree&#8221;);<br />
$tree-&gt;type(&#8220;xml&#8221;);<br />
$tree-&gt;encoding(&#8216;GB2312&#8242;);<br />
$tree-&gt;attributes( Array(&#8216;aaa&#8217; =&gt; 111, &#8216;bbb&#8217; =&gt; 222 ) );</p>
<p>$tree1 = new xml(&#8220;tree1&#8243;);<br />
$tree1-&gt;tag(&#8220;tree1&#8243;);<br />
$tree1-&gt;value(&#8216;aaaa&#8217;,true);</p>
<p>$tree2 = new xml(&#8220;tree2&#8243;,&#8221;123&#8243;);<br />
$tree2-&gt;attribute(&#8216;abc&#8217;,'cba&#8217;);</p>
<p>$tree-&gt;addNode($tree1);<br />
$tree-&gt;addNode($tree2);</p>
<p>header(&#8216;Content-Type: text/xml&#8217;);<br />
echo $tree-&gt;display();</p>
<p>/* 例子二<br />
$tree11 = new xml(&#8220;tagname&#8221;, &#8216;asdfasdf&#8217;);<br />
echo $tree11-&gt;display();</p>
<p>$tree22 = new xml(&#8216;tagname1&#8242;,123123, array( &#8216;bb&#8217; =&gt; 11 ));<br />
echo $tree22-&gt;display();</p>
<p>$tree33 = new xml(&#8216;tagname3&#8242;);<br />
echo $tree33-&gt;display();<br />
*/</p>
<p>class xml<br />
{<br />
var $NodeTag  = &#8220;&#8221;;  // 当前对象的标签名<br />
var $NodeType  = &#8220;node&#8221;; // 共有四种类型：element, node, xml<br />
var $NodeNodes  = array(); // 子结点集合<br />
var $NodeEncoding = &#8220;utf-8&#8243;; // 编码方式<br />
var $NodeAttributes = array(); // 属性集合<br />
var $NodeVersion = &#8220;1.0&#8243;; // 版本号<br />
var $cdata  = false; // 是否使用 cdata 分隔符<br />
var $NodeValue  = &#8220;&#8221;;  // 结点值</p>
<p>/*<br />
* 构造函数<br />
*/</p>
<p>function xml($strTag = NULL,$mixValue = NULL, $arrAttributes = NULL, $cdata = false)<br />
{<br />
if( !$strTag ) return false;<br />
$this-&gt;tag($strTag);<br />
if( is_array( $arrAttributes ) ) $this-&gt;attributes($arrAttributes);<br />
if( method_exists($mixValue, &#8220;type&#8221;) &amp;&amp; ( $mixValue-&gt;type() == &#8220;node&#8221; || $mixValue-&gt;type() == &#8220;element&#8221; ))<br />
{<br />
$this-&gt;addNode($mixValue);<br />
}<br />
else<br />
{<br />
if( is_string($mixValue) ) $this-&gt;cdata = true;<br />
$this-&gt;value($mixValue, $cdata);<br />
}<br />
return $this;<br />
}</p>
<p>/*<br />
* 返回子节点数量<br />
*/</p>
<p>function NodeCount()<br />
{<br />
return count($this-&gt;NodeNodes);<br />
}</p>
<p>/*<br />
* XML 文件版本号<br />
* 现行的 XML 文件中只有 1.0 版本<br />
*/</p>
<p>function version($strVersion = NULL)<br />
{<br />
if( !$strVersion ) return $this-&gt;NodeVersion;<br />
$this-&gt;NodeVersion = $strVersion;<br />
return true;<br />
}</p>
<p>/*<br />
* XML 文件编码<br />
*/</p>
<p>function encoding($strEncoding = NULL)<br />
{<br />
if( !$strEncoding ) return $this-&gt;NodeEncoding;<br />
$this-&gt;NodeEncoding = $strEncoding;<br />
return true;<br />
}</p>
<p>/*<br />
* 节点标签名<br />
*/</p>
<p>function tag($strTag = NULL)<br />
{<br />
if( !$strTag ) return $this-&gt;NodeTag;<br />
$this-&gt;NodeTag = $strTag;<br />
return true;<br />
}</p>
<p>/*<br />
* 设置节点属性<br />
*/</p>
<p>function attribute($strAttributeName = NULL, $mixAttributeValue = NULL)<br />
{<br />
if( !$strAttributeName ) return false;<br />
// 设置属性<br />
if( $mixAttributeValue )<br />
{<br />
$this-&gt;NodeAttributes[$strAttributeName] = $mixAttributeValue;<br />
}<br />
else // 删除属性<br />
{<br />
unset( $this-&gt;NodeAttributes[$strAttributeName] );<br />
}<br />
return true;<br />
}</p>
<p>/*<br />
* 设置节点属性集<br />
*/</p>
<p>function attributes($arrAttributes = NULL)<br />
{<br />
if( !$arrAttributes ) return false;<br />
if( !is_array($arrAttributes) ) return false;<br />
$this-&gt;NodeAttributes = $arrAttributes;<br />
return true;<br />
}</p>
<p>/*<br />
* 子节点集合<br />
*/<br />
function nodes($arrNodes = NULL)<br />
{<br />
if( !$arrNodes ) return $this-&gt;NodeNodes;<br />
if( !is_array($arrNodes) ) return false;<br />
$this-&gt;NodeNodes = $arrNodes;<br />
return true;<br />
}</p>
<p>/*<br />
* 节点类型<br />
*/</p>
<p>function type($strType = NULL)<br />
{<br />
if( !$strType ) return $this-&gt;NodeType;<br />
if( $strType != &#8220;xml&#8221; &amp;&amp; $strType != &#8220;node&#8221; &amp;&amp; $strType != &#8220;element&#8221; ) return false;<br />
$this-&gt;NodeType = $strType;<br />
return true;<br />
}</p>
<p>/*<br />
* 加入新的节点对象<br />
*/</p>
<p>function addNode($objNode = NULL)<br />
{<br />
if( !$objNode ) return false;<br />
// lcl 是 local 的缩写，lcl_type 即是 local_type 局部变量的缩写<br />
$lcl_type = $objNode-&gt;type();<br />
if( $lcl_type != &#8220;element&#8221; &amp;&amp; $lcl_type != &#8220;node&#8221; &amp;&amp; $lcl_type != &#8220;xml&#8221; ) return false;<br />
if( $lcl_type == &#8220;xml&#8221; ) $objNode-&gt;type(&#8220;node&#8221;);<br />
// 加入新的节点对象<br />
$this-&gt;NodeNodes[count($this-&gt;NodeNodes)] = $objNode;<br />
return true;<br />
}</p>
<p>/*<br />
* 删除指定的节点<br />
*/</p>
<p>function removeNodeByIndex($intIndex = 0)<br />
{<br />
return array_splice($this-&gt;NodeNodes, $intIndex-1, 1);<br />
}</p>
<p>/*<br />
* 删除指定的属性<br />
*/</p>
<p>function removeAttributeByIndex($intIndex = 0)<br />
{<br />
return array_splice($this-&gt;NodeAttributes, $intIndex-1, 1);<br />
}</p>
<p>/*<br />
* 节点值<br />
*/</p>
<p>function value($mixValue = &#8221; , $cdata = false)<br />
{<br />
if( !$mixValue ) return $this-&gt;NodeValue;<br />
if( $cdata ) $this-&gt;cdata = true;<br />
$this-&gt;NodeValue = $mixValue;<br />
return true;<br />
}</p>
<p>/*<br />
* 得到显示字符串<br />
*/</p>
<p>function display($src_encoding = NULL, $intDepth = 0)<br />
{<br />
$strDisplay = &#8220;&#8221;;<br />
$strAttribute = &#8220;&#8221;;</p>
<p>if( !$intDepth ) $intDepth = 0;</p>
<p>// 根节点<br />
if( $this-&gt;type() == &#8220;xml&#8221; )<br />
{<br />
$strDisplay .= &#8220;&lt;?xml version=\&#8221;" . $this-&gt;version() . &#8220;\&#8221; encoding=\&#8221;" . $this-&gt;encoding() . &#8220;\&#8221; ?&gt;\n&#8221;;<br />
}</p>
<p>// 缩近修正<br />
$TAB_FIX = str_repeat( &#8220;\t&#8221; , $intDepth);</p>
<p>// 属性<br />
if( ($lcl_count = count( $this-&gt;attributes() ) ) &gt; 0 )<br />
{<br />
// 有属性<br />
foreach( $this-&gt;NodeAttributes as $SingleAttribute =&gt; $SingleValue )<br />
{<br />
$strAttribute .= &#8216; &#8216; . $SingleAttribute . &#8216;=&#8221;&#8216; . $SingleValue . &#8216;&#8221;&#8216;;<br />
}<br />
}</p>
<p>// 生成标签头<br />
$strDisplay .= $TAB_FIX . &#8220;&lt;&#8221; . $this-&gt;NodeTag . $strAttribute;</p>
<p>// 节点<br />
if( ($lcl_counts = $this-&gt;NodeCount()) &gt; 0 )<br />
{<br />
// 关闭标签头<br />
$strDisplay .= &#8220;&gt;\n&#8221;;<br />
// 如果有子节点集<br />
foreach( $this-&gt;NodeNodes as $SingleNode )<br />
{<br />
$strDisplay .= $SingleNode-&gt;display($src_encoding, $intDepth+1);<br />
}<br />
$strDisplay .= &#8220;&lt;/&#8221; . $this-&gt;NodeTag . &#8220;&gt;\n&#8221;;<br />
}<br />
else<br />
{<br />
// 没有子节点<br />
if( !$this-&gt;NodeValue )<br />
{<br />
// 节点没有值<br />
// 关闭标签头<br />
$strDisplay .= &#8221; /&gt;&#8221;;<br />
}<br />
else<br />
{<br />
// 节点有值<br />
$strDisplay .= &#8220;&gt;\n&#8221;;<br />
$strDisplay .= $TAB_FIX;</p>
<p>if( $this-&gt;cdata )<br />
{<br />
$strDisplay .= $TAB_FIX . &#8220;&lt;![CDATA[" . ($src_encoding?iconv($src_encoding, $this-&gt;encoding() , $this-&gt;NodeValue):$this-&gt;NodeValue) . "]]&gt;\n&#8221;;<br />
}<br />
else<br />
{<br />
$strDisplay .= $TAB_FIX . ($src_encoding?iconv($src_encoding, $this-&gt;encoding() , $this-&gt;NodeValue):$this-&gt;NodeValue) . &#8220;\n&#8221;;<br />
}</p>
<p>$strDisplay .= $TAB_FIX . &#8220;&lt;/&#8221; . $this-&gt;NodeTag . &#8220;&gt;\n&#8221;;<br />
}</p>
<p>}<br />
return $strDisplay;<br />
}<br />
}</p>
<p>?&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/14.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

