Hi - I have a simple SAX handler set up, and schema validation errors are being 
caught by my structured error handler.  So far so good.

It appears that the userdata argument to xmlSAXUserParseMemory must be the 
xmlSchemaSAXPlugPtr returned by the call to xmlSchemaSAXPlug, and that this 
pointer is passed as the ctx pointer to the SAX handler callbacks.

Is there any way for me to make a userdata pointer of my choosing available to 
my SAX handler callbacks while still getting schema validation?

My code is below, thanks for any suggestions!
Lara

#include <iostream>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <memory.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xmlschemas.h>
#include <string>

std::string getFileContents( std::string filename )
{
  std::ifstream file ( filename );
  std::string line;
  std::ostringstream fileContents;
  while ( std::getline ( file,
                         line ) )
  {
    fileContents << line << "\n";
  }

  file.close ( );
  return fileContents.str ( );
}

void startElementNs( void * ctx, const xmlChar * localname, const xmlChar * 
prefix, const xmlChar * URI,
                     int nb_namespaces, const xmlChar ** namespaces, int 
nb_attributes, int nb_defaulted,
                      const xmlChar ** attributes)
{
  fprintf(stderr, "startElementNs: ctx = %p\n", (unsigned long)ctx );
  fprintf(stderr, "startElementNs: %s %s %s\n", (char*)prefix, 
(char*)localname, (char*)URI );
}

void endElementNs( void * ctx, const xmlChar * localname, const xmlChar * 
prefix, const xmlChar * URI)
{
  fprintf(stderr, "endElementNs: ctx = %p\n", (unsigned long)ctx );
  fprintf(stderr, "endElementNs: %s %s %s\n", (char*)prefix, (char*)localname, 
(char*)URI );
}

void structuredErrors(void *userdata, xmlErrorPtr error)
{
  fprintf(stderr, "Structured error userdata=%p\n", userdata );
  fprintf(stderr, "Structured error (%s, line %d): %s\n", error->file, 
error->line, error->message);
}

int main(int argc, const char * argv[])
{
   if ( argc != 3 )
   {
     fprintf( stderr, "Usage: %s <xml file> <schema file>\n", argv[0] );
     exit(1);
   }

   const char* filename = argv[1];
   const char* schema = argv[2];

   std::string xmlIn = getFileContents( filename );

   xmlSAXHandler *schemaValHandler = new xmlSAXHandler;
   memset( schemaValHandler, 0, sizeof(xmlSAXHandler) );
   schemaValHandler->initialized = XML_SAX2_MAGIC;
   schemaValHandler->error = NULL;
   schemaValHandler->warning = warning;
   schemaValHandler->startElementNs = startElementNs;
   schemaValHandler->endElementNs = endElementNs;
   schemaValHandler->startElement = NULL;
   schemaValHandler->endElement = NULL;

   xmlSchemaParserCtxtPtr parseCtxt = xmlSchemaNewParserCtxt(schema);
   xmlSchemaPtr xsdSchemas = xmlSchemaParse(parseCtxt);
   xmlSchemaValidCtxtPtr xsdValidCtxt = xmlSchemaNewValidCtxt(xsdSchemas);
   xmlSchemaSetValidStructuredErrors(xsdValidCtxt, structuredErrors, NULL );

   // userdata arg is set to the pointer to the original SAX user data pointer
   xmlSchemaValidCtxtPtr oldXsdValidCtxt = NULL;;
   void *ctxptr = &oldXsdValidCtxt;
   xmlSchemaSAXPlugPtr saxPlug = xmlSchemaSAXPlug(xsdValidCtxt, 
&schemaValHandler, &ctxptr );

   // !!!!!!!! the userdata in the second argument MUST be the 
xmlSchemaSAXPlugPtr, the pointer value is in
   // !!!!!!!! both saxPlug and ctxptr
   // !!!!!!!! This pointer is passed to functions such as startElementNsSplit 
that are configured in
   // !!!!!!!! the call to xmlSchemaSAXPlug, which cast the pointer to a 
xmlSchemaSAXPlugPtr, so if you
   // !!!!!!!! try to pass ANY other pointer, you'll get a crash
   int result = xmlSAXUserParseMemory( schemaValHandler, ctxptr, xmlIn.c_str(), 
xmlIn.length() );

   if ( result != 0 )
   {
      fprintf(stderr, "Failed to parse document.\n" );
   }

   xmlCleanupParser();
   xmlSchemaSAXUnplug( saxPlug );
   xmlSchemaFreeValidCtxt(xsdValidCtxt);
   xmlSchemaFree(xsdSchemas);
   xmlSchemaFreeParserCtxt(parseCtxt);
   delete schemaValHandler;

   return 0;
}


Lara Blatchford
Principal Engineer
Nteligen, LLC
lara.blatchf...@nteligen.com
(443) 864-5042 x110

[cid:image001.jpg@01D7F807.64086410]

_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xml@gnome.org
https://mail.gnome.org/mailman/listinfo/xml

Reply via email to