' /* This is simple demonstration of how to use expat. This program
' reads an XML document from standard input and writes a line with the
' name of each element to standard output indenting child elements by
' one tab stop more than their parent element. */
'
'
$NOMAIN
' ENUM
' TYPE_ELEMENT = 0
' TYPE_ATTRIBUTE
' END ENUM
' Type XmlData
' idx
' key$
' value$
' End Type
' GLOBAL UD as XmlData
'DIM DYNAMIC rowText$[64]
'REDIM rowText$ [nColCount]
'GLOBAL DYNAMIC FileName$[10]
' search for text files - find the first file
' A$ = FINDFIRST$(APPEXEPATH$ + mask$)
' WHILE A$ > ""
' tmpYear$ = TRIM$(LEFT$(A$, 4)) 'get year from filename
' IF tmpYear$ = Year$ THEN 'make sure it's the correct year file
' tmpVar$ = RIGHT$(A$, LEN(A$)-4) 'remove the year from the string
' FileName$[count] = tmpVar$ 'add filename to array
' IF cnt = 0 THEN REDIM PRESERVE FileName$[count+10] : cnt = 0
' count++ : cnt++
' END IF
' find the rest
' A$ = FINDNEXT$
' WEND
' FREE DYNAMIC FileName$
#INCLUDE "C:\Program Files\Expat 2.0.1\Source\lib\expat.h"
$LIBRARY "libexpat.lib"
CONST BUFFSIZE = 8192
GLOBAL parser AS XML_Parser
GLOBAL EArray$[1000]
GLOBAL AArray$[1000]
GLOBAL EIndex AS INTEGER
GLOBAL AIndex AS INTEGER
GLOBAL ElementData$
GLOBAL ElementCnt
GLOBAL AttributeData$
GLOBAL AttributeCnt
FUNCTION main(ARGC, ARGV AS char PTR PTR)
DIM RAW Buff[BUFFSIZE] AS char
DIM TimerStart, TimerEnd, TotalTime
DIM fname$
EIndex = 0
AIndex = 0
ElementCnt = 0
AttributeCnt = 0
fname$ = GETFILENAME$("Load XML File","XML Files (*.xml)|*.xml")
IF NOT *fname$ THEN
PRINT "Unable to open xml file"
END = 1
END IF
OPEN BCXSPLITPATH$(fname$, FNAME|FEXT) FOR INPUT AS FP1
TimerStart = TIMER
'create a parser
parser = CreateParser()
'set a pointer to the SciStyle TYPE
'as the first parameter to startElement
'and endElement (userData AS void PTR)
' XML_SetUserData (parser, &UD)
'call the expat parser to do the work
IF NOT Parse(parser, FP1) THEN
Print "Parsing failed"
END = 1
END IF
CLOSE FP1
TimerEnd = TIMER
TotalTime = TimerEnd - TimerStart
PRINT "Total Number of Elements (keys) = " + STR$(ElementCnt--)
PRINT "Total Number of Attributes = " + STR$(AttributeCnt--)
PRINT "Total Time for parse = " + STR$(TotalTime)
'just what it says...
XML_ParserFree (parser)
FUNCTION = 0
END FUNCTION
SUB PushElement(element$)
ElementCnt++
EIndex++
EArray$[EIndex] = element$
END SUB
FUNCTION PopElement$()
DIM s$
's$ = "Element: " + EArray$[EIndex]
s$ = EArray$[EIndex]
IF *EArray$[EIndex] THEN
EIndex--
IF EIndex < 0 THEN EIndex = 0
FUNCTION = s$
END IF
FUNCTION = ""
END FUNCTION
SUB PushAttribute(element$)
AttributeCnt++
AIndex++
AArray$[AIndex] = element$
END SUB
FUNCTION PopAttribute$()
DIM s$
's$ = "Attribute: " + AArray$[AIndex]
s$ = AArray$[AIndex]
IF *AArray$[AIndex] THEN
AIndex--
IF AIndex < 0 THEN AIndex = 0
FUNCTION = s$
END IF
FUNCTION = ""
END FUNCTION
SUB startElement (userData AS void PTR, aname AS LPCCH, atts AS const char PTR PTR)
DIM numAttr, i
DIM s$
s$ = aname$
IF *s$ THEN
PushElement(s$)
END IF
'find out if there are any attributes
numAttr = XML_GetSpecifiedAttributeCount(parser)
IF numAttr > 0 THEN 'send to the attribute handler function
FOR i = 0 TO numAttr - 1 STEP 2
IF *atts$[i] THEN
s$ = atts$[i] + " = " + atts$[i+1]
PushAttribute(s$)
END IF
PRINT PopAttribute$()
NEXT i
END IF
END SUB
SUB charData(userData AS void PTR, s AS const XML_Char PTR, length)
DIM AUTO CurElement$
strncpy(CurElement, s, length)
IF TRIM$(CurElement) > "" THEN
PRINT PopElement$() + " = " + TRIM$(CurElement$)
END IF
END SUB
SUB endElement (userData AS void PTR, aname AS LPCCH)
'PopElement()
END SUB
FUNCTION CreateParser() AS XML_Parser
DIM RAW p AS XML_Parser
p = XML_ParserCreate(NULL)
IF NOT p THEN
PRINT "Couldn't allocate memory for parser"
EXIT FUNCTION
ELSE
XML_SetElementHandler(p, startElement, endElement)
XML_SetCharacterDataHandler(p, charData)
FUNCTION = p
END IF
FUNCTION = 0
END FUNCTION
FUNCTION Parse(p AS XML_Parser, FP AS FILE) AS BOOL
DIM Buff[BUFFSIZE] AS CHAR
DO
DIM RAW done
DIM RAW length
length = (int)fread(Buff, 1, BUFFSIZE, FP)
done = CBOOL(length < BUFFSIZE)
IF XML_Parse(p, Buff, length, done) = XML_STATUS_ERROR THEN
PRINT "Parse error at line " , XML_GetCurrentLineNumber(p), _
" Error code: ", XML_ErrorString$(XML_GetErrorCode(p))
FUNCTION = FALSE
END IF
LOOP WHILE NOT done
FUNCTION = TRUE
END FUNCTION