Example of creating a RELAX NG (RNG) validator to be called during validation.
#include <iostream>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/relaxng.h>
#include <stdarg.h>
std::vector<std::string> warnings;
std::vector<std::string> errors;
void logWarning(void *ctx, const char *msg, ...)
{
char buffer[1000];
va_list args;
va_start (args, msg);
vsprintf (buffer,msg, args);
va_end (args);
warnings.push_back(buffer);
}
void logError(
void *ctx,
const char *msg, ...)
{
char buffer[1000];
va_list args;
va_start (args, msg);
vsprintf (buffer,msg, args);
va_end (args);
errors.push_back(buffer);
}
{
private:
std::string mSchema;
public:
void setSchema(const std::string& schemaFile)
{
mSchema =schemaFile;
}
const std::string& getSchema() const { return mSchema; }
RNGValidator(
const std::string& schema) :
SBMLValidator(), mSchema(schema) {}
RNGValidator(
const RNGValidator& orig) :
SBMLValidator(orig), mSchema(orig.mSchema) {
}
virtual ~RNGValidator() {}
virtual SBMLValidator* clone()
const {
return new RNGValidator(*
this); }
virtual unsigned int validate() {
if (getDocument() == NULL || getModel() == NULL)
return 0;
if (mSchema.empty())
return 0;
if (getModel()->getNumReactions() == 0 && getModel()->getNumRules() == 0)
return 0;
warnings.clear();
errors.clear();
xmlDoc *doc;
xmlRelaxNGPtr schema;
xmlRelaxNGValidCtxtPtr validctxt;
xmlRelaxNGParserCtxtPtr rngparser;
doc = xmlParseMemory(sbmlDoc.c_str(), (int)(sbmlDoc.length()));
rngparser = xmlRelaxNGNewParserCtxt(mSchema.c_str());
schema = xmlRelaxNGParse(rngparser);
validctxt = xmlRelaxNGNewValidCtxt(schema);
xmlRelaxNGSetParserErrors (rngparser,
&logWarning,
(void *) getErrorLog());
xmlRelaxNGSetValidErrors (validctxt,
&logWarning,
(void *) getErrorLog());
xmlRelaxNGValidateDoc(validctxt, doc);
xmlRelaxNGFree(schema);
xmlRelaxNGFreeValidCtxt(validctxt);
xmlRelaxNGFreeParserCtxt(rngparser);
xmlFreeDoc(doc);
unsigned int numErrors = 0;
for (size_t i = 0; i < warnings.size(); ++i)
{
warnings[i],
0, 0,
));
}
for (size_t i = 0; i < errors.size(); ++i)
{
errors[i],
0, 0,
));
numErrors ++;
}
return numErrors;
}
};
int
main (int argc, char *argv[])
{
if (argc < 2)
{
cout << endl << "Usage: rngvalidator filename [schema]" << endl << endl;
return 1;
}
const char* filename = argv[1];
const char* schema = argc > 2 ? argv[2] : NULL;
if (schema != NULL)
document->addValidator(new RNGValidator(schema));
unsigned long long start, stop;
start = getCurrentMillis();
stop = getCurrentMillis();
cout << " validation time (ms): " << stop - start << endl<< endl;
return numErrors;
}