Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: XML
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++;
    /* could call mixed content legal tag check routine here e.g.
    if (!isvalidmixedcontenttag(qName, parser->state)) return sin(); */
    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; /* set initial state (root element) */
  }
  else if (parser->state == STORIES && !strcmp(qName, "story")) {
    /* initialize new 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;
  }
  /* these would normally be done with a little more short circuiting: */
  else if (parser->state == STORY && !strcmp(qName, "title")) {
    parser->inContent++; /* STORY_TITLE tag allows normal content */
    parser->state = STORY_TITLE;
  }
  else if (parser->state == STORY && !strcmp(qName, "author")) {
    parser->inContent++; /* STORY_AUTHOR tag allows normal content */
    parser->state = STORY_AUTHOR;
  }
  else if (parser->state == STORY && !strcmp(qName, "body")) {
    parser->inMixedContent++; /* STORY_BODY tag allows mixed content */
    parser->state = STORY_BODY;
  }
  else {
    printf("Unexpected tag: %s\nFile is not in zen story format!\n", qName);
    return XML_ABORT;
  }
  /* push the new state: */
  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 this is last mixed content tag (the tag
    that put us in mixed content), we POP the state,
    otherwise we just decrement the counter and return OK: */
    if ((--parser->inMixedContent) > 0) return XML_OK;
  }
 
  if (STACK_POP(parser->stateStack, &parser->state)) {
    /* test the endTag here by popping and testing parser->state
    (which is the state that is ending) */
    XMLCH *s = (XMLCH*)NULL;
 
    switch(parser->state) {
      case STORY_TITLE: /* you should check duplicate title etc. here */
        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) {
      /* normalize buffer, note that XMLNormalizeBuf doesn't nul terminate the
      buffer: */
      int len = XMLNormalizeBuf(s, parser->textBuf.len);
      if (len < parser->textBuf.len) s[len] = '\0';
      /* we'll reuse Stringbuf just setting its length to 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) {
    /* if either inContent or inMixedContent is set,
       append data into Stringbuf: */
    ASSERT_MEM_ABORT(XMLStringbuf_Append(&parser->textBuf,
      (XMLCH*)Chars, cbChars));
  }
  else {
    /* this tag cannot contain character data: */
    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;
  }
 
  /* init Stringbuf: blockSize 256, no pre-allocation: */
  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)) {
 
    /* present the stories (we'll free the strings in the same loop) : */
    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);
 
/* stack macros (from xmldef.h) */
#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>
Posted 29-Sep-12 8:51am
Edited 29-Sep-12 8:53am
(no name)53.3K
v2
Comments
aspnet_regiis at 29-Sep-12 14:28pm
   
This code works when executed from a C compiler
mvigsnhwar at 29-Sep-12 14:44pm
   
sir can u help me how to understand this program clearly and how this syntax works
aspnet_regiis at 30-Sep-12 5:56am
   
Okay..Which part of the program specifically do you have problem in understanding ?
Sergey Alexandrovich Kryukov at 1-Oct-12 0:52am
   
"How it works" is not a valid question. Not clear what help is expected.
--SA
mvigsnhwar at 2-Oct-12 2:47am
   
Okay sir ,start and end element section. i m unable to understand how it works with a corresponding xml file
mvigsnhwar at 11-Oct-12 12:59pm
   
Dear sir,i understood that this program parses the xml file for the known tag names.
Eg:<title>,,<body>
but i want to parse the xml file without hardcoding the tag names.
 
could anyone help on how to parse the xml file if tag names are unknown using libparsifal library ?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Marcin Kozub 265
1 Richard MacCutchan 239
2 OriginalGriff 208
3 Sergey Alexandrovich Kryukov 185
4 Praneet Nadkar 167
0 OriginalGriff 7,913
1 Sergey Alexandrovich Kryukov 7,232
2 DamithSL 5,604
3 Manas Bhardwaj 4,986
4 Maciej Los 4,865


Advertise | Privacy | Mobile
Web03 | 2.8.1411023.1 | Last Updated 29 Sep 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100