/**
   Reader using Libxml (the Gnome xml parser)
   Written by Scriptol S.A.R.L - www.scriptol.com

   Goal:
   Parses an xml document and analyze it in memory...
   ... then you can perform whatever you want on the content.
   I use a modified version to load xml documents into Scriptol programs.

   Usage:
   reader document.xml

  */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libxml/parser.h>
#include <libxml/xmlreader.h>


void indent(int level)
{
  int i;
  for(i = 0; i <= level; i++)
  {
    printf("  ");
  }
}


void analyze(const char *s, xmlChar *value)
{
#ifdef DEBUG
   printf("%s", s);
   if(value != NULL)
    {
      printf(" %s", value);
    }
   printf("\n");
#else
  s = NULL;
  value = NULL;
#endif
}


void processNode(xmlTextReaderPtr reader)
{
   xmlChar *name, *value, *attName, *attValue;
   int natt, no;
   int type;

   type = xmlTextReaderNodeType(reader);

   if(type != XML_READER_TYPE_ATTRIBUTE)
   {
     indent(xmlTextReaderDepth(reader));
   }

   name = xmlTextReaderName(reader);
   if(name == NULL)
   {
      name = xmlStrdup(BAD_CAST "--");
   }

   value = xmlTextReaderValue(reader);

   switch(type)
   {
     case XML_READER_TYPE_ELEMENT:
          printf("<%s", name);
          natt = xmlTextReaderAttributeCount(reader);
          for(no = 0; no < natt; no++)
          {
            xmlTextReaderMoveToAttributeNo(reader, no);
            processNode(reader);
          }
          printf(" >\n");
          break;
     case XML_READER_TYPE_END_ELEMENT:
          printf("</%s>\n", name);
          break;
     case XML_READER_TYPE_ATTRIBUTE:
          printf(" %s=%s", name, value);
          break;
     case XML_READER_TYPE_TEXT:
          if(value != NULL)
          {
            printf("%s\n", value);
          }
          break;
     case XML_READER_TYPE_CDATA:
          analyze("cdata", value);
          break;
     case XML_READER_TYPE_ENTITY_REFERENCE:
          analyze("entity ref", value);
          break;
     case XML_READER_TYPE_ENTITY:
          analyze("entity", value);
          break;
     case XML_READER_TYPE_PROCESSING_INSTRUCTION:
          if(value != NULL)
          {
           printf("<?%s %s ?>\n", name, value);
          }
          break;
     case XML_READER_TYPE_COMMENT:
          if(value != NULL)
          {
            printf("<!--%s-->\n", value);
          }
          break;
     case XML_READER_TYPE_DOCUMENT:
          analyze("document", value);
          break;
     case XML_READER_TYPE_DOCUMENT_TYPE:
          analyze("dtd", value);
          break;
     case XML_READER_TYPE_DOCUMENT_FRAGMENT:
          analyze("fragment", value);
          break;
     case XML_READER_TYPE_NOTATION:
          analyze("notation", value);
          break;
     case XML_READER_TYPE_WHITESPACE:
          break;
     case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
          break;
     case XML_READER_TYPE_END_ENTITY:
          analyze("end entity", value);
          break;
     case XML_READER_TYPE_XML_DECLARATION:
          analyze("xml", value);
          break;
     default:
          puts("none");
          break;
   }

/*
   printf("depth=%d type=%d %s empty?%d\n",
          xmlTextReaderDepth(reader),
          xmlTextReaderNodeType(reader),
          name,
          xmlTextReaderIsEmptyElement(reader)
          );
*/
   xmlFree(name);

   if(value != NULL)
   {
      xmlFree(value);
   }
}

void loadxml(char *fname)
{

 xmlTextReaderPtr reader;
 int ret;

 reader = xmlNewTextReaderFilename(fname);
 if(reader == NULL)
 {
   puts("not created");
   return;
 }

 ret = xmlTextReaderRead(reader);
 while(ret == 1)
 {
   processNode(reader);
   ret = xmlTextReaderRead(reader);
 }


 xmlFreeTextReader(reader);
 if(ret)
 {
   puts("not parsed");
 }

}

int main(int argc, char *argv[])
{
  if(argc < 2)
  {
     puts("Reader - www.scriptol.com");
     puts("Usage:");
     puts("reader fname");
     return(1);
  }

  loadxml(argv[1]);
  return(1);
}
