HOW THIS WORKS ????????????
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "libparsifal/parsifal.h"
#include "zenstory.h"
int StartElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName, LPXMLVECTOR atts)
{
STORYPARSER *parser = (STORYPARSER*)UserData;
if (parser->inMixedContent) {
parser->inMixedContent++;
return XML_OK;
}
else {
int *pstate = STACK_PEEK(parser->stateStack);
parser->state = (pstate) ? *pstate : NONE;
}
if (parser->state == NONE && !strcmp(qName, "stories")) {
parser->state = STORIES;
}
else if (parser->state == STORIES && !strcmp(qName, "story")) {
parser->curStory = XMLVector_Append(parser->stories, NULL);
ASSERT_MEM_ABORT(parser->curStory);
parser->curStory->title = (char*)NULL;
parser->curStory->author = (char*)NULL;
parser->curStory->body = (char*)NULL;
parser->state = STORY;
}
else if (parser->state == STORY && !strcmp(qName, "title")) {
parser->inContent++;
parser->state = STORY_TITLE;
}
else if (parser->state == STORY && !strcmp(qName, "author")) {
parser->inContent++;
parser->state = STORY_AUTHOR;
}
else if (parser->state == STORY && !strcmp(qName, "body")) {
parser->inMixedContent++;
parser->state = STORY_BODY;
}
else {
printf("Unexpected tag: %s\nFile is not in zen story format!\n", qName);
return XML_ABORT;
}
ASSERT_MEM_ABORT(STACK_PUSH(parser->stateStack, &parser->state));
return XML_OK;
}
int EndElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName)
{
STORYPARSER *parser = (STORYPARSER*)UserData;
if (parser->inContent)
parser->inContent = 0;
else if (parser->inMixedContent) {
if ((--parser->inMixedContent) > 0) return XML_OK;
}
if (STACK_POP(parser->stateStack, &parser->state)) {
XMLCH *s = (XMLCH*)NULL;
switch(parser->state) {
case STORY_TITLE:
s = strdup(XMLStringbuf_ToString(&parser->textBuf));
ASSERT_MEM_ABORT(s);
parser->curStory->title = s;
break;
case STORY_AUTHOR:
s = strdup(XMLStringbuf_ToString(&parser->textBuf));
ASSERT_MEM_ABORT(s);
parser->curStory->author = s;
break;
case STORY_BODY:
s = strdup(XMLStringbuf_ToString(&parser->textBuf));
ASSERT_MEM_ABORT(s);
parser->curStory->body = s;
break;
}
if (s) {
int len = XMLNormalizeBuf(s, parser->textBuf.len);
if (len < parser->textBuf.len) s[len] = '\0';
ASSERT_MEM_ABORT(XMLStringbuf_SetLength(&parser->textBuf, 0));
}
}
return XML_OK;
}
int Characters(void *UserData, const XMLCH *Chars, int cbChars)
{
STORYPARSER *parser = (STORYPARSER*)UserData;
if (parser->inContent || parser->inMixedContent) {
ASSERT_MEM_ABORT(XMLStringbuf_Append(&parser->textBuf,
(XMLCH*)Chars, cbChars));
}
else {
puts("Character data was not expected here!");
return XML_ABORT;
}
return XML_OK;
}
void ErrorHandler(LPXMLPARSER parser)
{
if (parser->ErrorCode != ERR_XMLP_ABORT)
printf("Parsing error: %s\n", parser->ErrorString);
printf("ErrorLine: %d ErrorColumn: %d\n", parser->ErrorLine, parser->ErrorColumn);
}
int cstream(BYTE *buf, int cBytes, int *cBytesActual, void *inputData)
{
*cBytesActual = fread(buf, 1, cBytes, (FILE*)inputData);
return (*cBytesActual < cBytes);
}
int main(int argc, char* argv[])
{
STORYPARSER sparser;
LPXMLPARSER parser;
if (!XMLParser_Create(&parser)) {
puts("Error creating parser!");
return 1;
}
if (!XMLVector_Create(&sparser.stateStack, 6, sizeof(int))) {
puts("Error creating stateStack in main()");
return 1;
}
if (!XMLVector_Create(&sparser.stories, 6, sizeof(ZENSTORY))) {
puts("Error creating stories vector in main()");
return 1;
}
XMLStringbuf_Init(&sparser.textBuf, 256, 0);
sparser.parser = parser;
sparser.inMixedContent = sparser.inContent = 0;
parser->UserData = &sparser;
parser->errorHandler = ErrorHandler;
parser->startElementHandler = StartElement;
parser->endElementHandler = EndElement;
parser->charactersHandler = Characters;
if (XMLParser_Parse(parser, cstream, stdin, 0)) {
int i;
ZENSTORY *story;
for (i=0; i<sparser.stories->length; i++) {
story = XMLVector_Get(sparser.stories, i);
if (story) {
if (story->title) {
printf("title: %s\n", story->title);
free(story->title);
}
if (story->author) {
printf("author: %s\n", story->author);
free(story->author);
}
if (story->body) {
printf("story: %s\n",story->body);
free(story->body);
}
}
}
}
XMLParser_Free(parser);
XMLStringbuf_Free(&sparser.textBuf);
XMLVector_Free(sparser.stories);
XMLVector_Free(sparser.stateStack);
return 0;
}
Zenstory.h
int StartElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName, LPXMLVECTOR atts);
int EndElement(void *UserData, const XMLCH *uri, const XMLCH *localName, const XMLCH *qName);
int Characters(void *UserData, const XMLCH *Chars, int cbChars);
void ErrorHandler(LPXMLPARSER parser);
int cstream(BYTE *buf, int cBytes, int *cBytesActual, void *inputData);
#define STACK_PUSH(stack,item) (XMLVector_Append((stack), (item)))
#define STACK_PEEK(stack) (XMLVector_Get((stack),(stack)->length-1))
#define STACK_REMOVE(stack) (XMLVector_Remove((stack), (stack)->length-1))
#define STACK_POP(stack,item) \
( ((stack)->length) ? (memcpy((item), STACK_PEEK((stack)), (stack)->itemSize), \
STACK_REMOVE((stack)), (item)) : NULL)
#define ASSERT_MEM_ABORT(p) if (!(p)) { printf("Out of memory! Line: %d\n", __LINE__); return XML_ABORT; }
enum tagSTATES { NONE, STORIES, STORY, STORY_TITLE, STORY_AUTHOR, STORY_BODY } STATES;
typedef struct tagZENSTORY {
char *title;
char *author;
char *body;
} ZENSTORY;
typedef struct tagSTORYPARSER {
LPXMLPARSER parser;
XMLSTRINGBUF textBuf;
LPXMLVECTOR stateStack;
int state;
int inContent;
int inMixedContent;
LPXMLVECTOR stories;
ZENSTORY *curStory;
} STORYPARSER;
</sparser.stories-></stdlib.h></string.h></stdio.h>