' /* 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