//-----------------------------------------
bool RngValidator::run(const std::string& xml_file_pathname, const std::string& rng_file_pathname)
//-----------------------------------------
{
    // TODO handle multiple RNG files (eg viz)
    
    // RELAX NG Parser Context
    xmlRelaxNGParserCtxtPtr ctxt = xmlRelaxNGNewParserCtxt(rng_file_pathname.c_str());
    xmlRelaxNGSetParserErrors(ctxt,
                              (xmlRelaxNGValidityErrorFunc)RngValidator::rngErr,
                              (xmlRelaxNGValidityWarningFunc)RngValidator::rngWarn,
                              NULL);

    xmlRelaxNGPtr schema = xmlRelaxNGParse(ctxt);
    xmlRelaxNGFreeParserCtxt(ctxt);

    xmlTextReaderPtr reader = xmlNewTextReaderFilename(xml_file_pathname.c_str());

    xmlTextReaderRelaxNGSetSchema(reader, schema);

    xmlTextReaderSetErrorHandler(reader, (xmlTextReaderErrorFunc)RngValidator::readerErr, NULL);
    xmlTextReaderSetStructuredErrorHandler(reader, (xmlStructuredErrorFunc)RngValidator::structErr, NULL);

    while (xmlTextReaderRead(reader));

    const bool valid = xmlTextReaderIsValid(reader) == 1;

    xmlFreeTextReader(reader);
    xmlRelaxNGFree(schema);

    return valid;
}
    /*!
     * \brief Private constructor from a libxml pointer
     *
     * Do the real configuration from a libxml pointer
     * \param pctxt[in]: lib xml document pointer
     */
    void QRelaxNGvalidator::finish(const void * pctxt)
    {
        //  Parse schema
        this->rng = xmlRelaxNGParse((xmlRelaxNGParserCtxtPtr)pctxt);
        xmlRelaxNGFreeParserCtxt((xmlRelaxNGParserCtxtPtr)pctxt);
        if(!rng) {
            goto schemaerror;
        }

        //  Create a validation context
        vctxt = xmlRelaxNGNewValidCtxt((xmlRelaxNGPtr)this->rng);
        if(!vctxt) {
            goto contexterror;
        }

        /* Ask the validation parser to return error */
        xmlRelaxNGSetValidErrors((xmlRelaxNGValidCtxtPtr)this->vctxt,
                (xmlRelaxNGValidityErrorFunc) fprintf,
                (xmlRelaxNGValidityWarningFunc) fprintf,
                stderr);
        return;

schemaerror:
        this->raiseError(QString("Schema ") + this->filename + QString(" has an error"));
        return;
contexterror:
        this->raiseError(QString("Could not create validation context for ")
                + this->filename + QString("schema"));
        xmlRelaxNGFree((xmlRelaxNGPtr)this->rng);
        return;
    }
Exemple #3
0
	RelaxNGSchema(const std::string& grammar)
	{
		xmlRelaxNGParserCtxtPtr ctxt = xmlRelaxNGNewMemParserCtxt(grammar.c_str(), (int)grammar.size());
		m_Schema = xmlRelaxNGParse(ctxt);
		xmlRelaxNGFreeParserCtxt(ctxt);

		if (m_Schema == NULL)
			LOGERROR("RelaxNGValidator: Failed to compile schema");
	}
void RelaxNGSchema::parse_context(_xmlRelaxNGParserCtxt* context)
{
  xmlResetLastError();
  release_underlying();

  if (!context)
    throw parse_error("RelaxNGSchema::parse_context(): Could not create parser context.\n" + format_xml_error());
  
  RelaxNGSchemaParserContextHolder holder(context);

  pimpl_->schema = xmlRelaxNGParse(context);
  if (!pimpl_->schema)
    throw parse_error("RelaxNGSchema::parse_context(): Schema could not be parsed.\n" + format_xml_error());
}
Exemple #5
0
/*
 * call-seq:
 *  from_document(doc)
 *
 * Create a new RelaxNG schema from the Nokogiri::XML::Document +doc+
 */
static VALUE from_document(VALUE klass, VALUE document)
{
  xmlDocPtr doc;
  xmlRelaxNGParserCtxtPtr ctx;
  xmlRelaxNGPtr schema;
  VALUE errors;
  VALUE rb_schema;

  Data_Get_Struct(document, xmlDoc, doc);

  /* In case someone passes us a node. ugh. */
  doc = doc->doc;

  ctx = xmlRelaxNGNewDocParserCtxt(doc);

  errors = rb_ary_new();
  Nokogiri_install_error_catcher(errors);

#ifdef HAVE_XMLRELAXNGSETPARSERSTRUCTUREDERRORS
  xmlRelaxNGSetParserStructuredErrors(
    ctx,
    Nokogiri_error_array_pusher,
    (void *)errors
  );
#endif

  schema = xmlRelaxNGParse(ctx);

  Nokogiri_remove_error_catcher();

  if(NULL == schema) {
    xmlErrorPtr error = xmlGetLastError();
    if(error)
      Nokogiri_error_raise(NULL, error);
    else
      rb_raise(rb_eRuntimeError, "Could not parse document");

    return Qnil;
  }

  rb_schema = Data_Wrap_Struct(klass, 0, dealloc, schema);
  rb_iv_set(rb_schema, "@errors", errors);

  return rb_schema;
}
XMLValidationRelaxNG::XMLValidationRelaxNG(const char *path, std::string * error): XMLValidation()
{
    char *expandedPath = expandPathVariable(const_cast < char *>(path));
    if (expandedPath)
    {
        xmlRelaxNGParserCtxt *pctxt = xmlRelaxNGNewParserCtxt(expandedPath);
        FREE(expandedPath);
        if (!pctxt)
        {
            if (errorBuffer)
            {
                delete errorBuffer;
            }
            errorBuffer = new std::string(gettext("Cannot create a validation context"));
            *error = *errorBuffer;
        }
        else
        {
            validationFile = (void *)xmlRelaxNGParse(pctxt);
            xmlRelaxNGFreeParserCtxt(pctxt);
            if (!validationFile)
            {
                if (errorBuffer)
                {
                    delete errorBuffer;
                }
                errorBuffer = new std::string(gettext("Cannot parse the Relax NG grammar"));
                *error = *errorBuffer;
            }
            else
            {
                openValidationFiles.push_back(this);
            }
        }
    }
    else
    {
        *error = std::string(gettext("Invalid file name: ")) + std::string(path);
    }

    scope->registerPointers(validationFile, this);
    id = scope->getVariableId(*this);
}
Exemple #7
0
/* {{{ _xmlreader_get_relaxNG */
static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, size_t source_len, size_t type,
											xmlRelaxNGValidityErrorFunc error_func,
											xmlRelaxNGValidityWarningFunc warn_func)
{
	char *valid_file = NULL;
	xmlRelaxNGParserCtxtPtr parser = NULL;
	xmlRelaxNGPtr           sptr;
	char resolved_path[MAXPATHLEN + 1];

	switch (type) {
	case XMLREADER_LOAD_FILE:
		valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN );
		if (!valid_file) {
			return NULL;
		}
		parser = xmlRelaxNGNewParserCtxt(valid_file);
		break;
	case XMLREADER_LOAD_STRING:
		parser = xmlRelaxNGNewMemParserCtxt(source, source_len);
		/* If loading from memory, we need to set the base directory for the document
		   but it is not apparent how to do that for schema's */
		break;
	default:
		return NULL;
	}

	if (parser == NULL) {
		return NULL;
	}

	if (error_func || warn_func) {
		xmlRelaxNGSetParserErrors(parser,
			(xmlRelaxNGValidityErrorFunc) error_func,
			(xmlRelaxNGValidityWarningFunc) warn_func,
			parser);
	}
	sptr = xmlRelaxNGParse(parser);
	xmlRelaxNGFreeParserCtxt(parser);

	return sptr;
}
Exemple #8
0
static xmlRelaxNGPtr _xmlreader_get_relaxNG(String source, int type,
                                            xmlRelaxNGValidityErrorFunc error_func,
                                            xmlRelaxNGValidityWarningFunc warn_func )
{
  xmlRelaxNGParserCtxtPtr parser = NULL;
  xmlRelaxNGPtr           sptr;
  String valid_file;

  switch (type) {
    case XMLREADER_LOAD_FILE:
      valid_file = _xmlreader_get_valid_file_path(source.c_str());
      if (valid_file.empty()) {
        return NULL;
      }
      parser = xmlRelaxNGNewParserCtxt(valid_file.c_str());
      break;
    case XMLREADER_LOAD_STRING:
      parser = xmlRelaxNGNewMemParserCtxt(source.data(), source.size());
      /* If loading from memory, we need to set the base directory for the document
        but it is not apparent how to do that for schema's */
      break;
    default:
      return NULL;
  }

  if (parser == NULL) {
    return NULL;
  }

  if (error_func || warn_func) {
  xmlRelaxNGSetParserErrors(parser,
    (xmlRelaxNGValidityErrorFunc) error_func,
    (xmlRelaxNGValidityWarningFunc) warn_func,
    parser);
  }
  sptr = xmlRelaxNGParse(parser);
  xmlRelaxNGFreeParserCtxt(parser);

  return sptr;
}
Exemple #9
0
/*
 * call-seq:
 *  read_memory(string)
 *
 * Create a new RelaxNG from the contents of +string+
 */
static VALUE read_memory(VALUE klass, VALUE content)
{
  xmlRelaxNGParserCtxtPtr ctx = xmlRelaxNGNewMemParserCtxt(
      (const char *)StringValuePtr(content),
      (int)RSTRING_LEN(content)
  );
  xmlRelaxNGPtr schema;
  VALUE errors = rb_ary_new();
  VALUE rb_schema;

  Nokogiri_install_error_catcher(errors);

#ifdef HAVE_XMLRELAXNGSETPARSERSTRUCTUREDERRORS
  xmlRelaxNGSetParserStructuredErrors(
    ctx,
    Nokogiri_error_array_pusher,
    (void *)errors
  );
#endif

  schema = xmlRelaxNGParse(ctx);

  Nokogiri_remove_error_catcher();
  xmlRelaxNGFreeParserCtxt(ctx);

  if(NULL == schema) {
    xmlErrorPtr error = xmlGetLastError();
    if(error)
      Nokogiri_error_raise(NULL, error);
    else
      rb_raise(rb_eRuntimeError, "Could not parse document");

    return Qnil;
  }

  rb_schema = Data_Wrap_Struct(klass, 0, dealloc, schema);
  rb_iv_set(rb_schema, "@errors", errors);

  return rb_schema;
}
/**
 * Parse elements from the configuration file.
 *
 */
ods_status
parse_file_check(const char* cfgfile, const char* rngfile)
{
    xmlDocPtr doc = NULL;
    xmlDocPtr rngdoc = NULL;
    xmlRelaxNGParserCtxtPtr rngpctx = NULL;
    xmlRelaxNGValidCtxtPtr rngctx = NULL;
    xmlRelaxNGPtr schema = NULL;

    if (!cfgfile || !rngfile) {
        ods_log_error("[%s] no cfgfile or rngfile", parser_str);
        return ODS_STATUS_ASSERT_ERR;
    }
    ods_log_assert(cfgfile);
    ods_log_assert(rngfile);
    ods_log_debug("[%s] check cfgfile %s with rngfile %s", parser_str,
        cfgfile, rngfile);

    /* Load XML document */
    doc = xmlParseFile(cfgfile);
    if (doc == NULL) {
        ods_log_error("[%s] unable to read cfgfile %s", parser_str,
            cfgfile);
        return ODS_STATUS_XML_ERR;
    }
    /* Load rng document */
    rngdoc = xmlParseFile(rngfile);
    if (rngdoc == NULL) {
        ods_log_error("[%s] unable to read rngfile %s", parser_str,
            rngfile);
        xmlFreeDoc(doc);
        return ODS_STATUS_XML_ERR;
    }
    /* Create an XML RelaxNGs parser context for the relax-ng document. */
    rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
    if (rngpctx == NULL) {
        xmlFreeDoc(rngdoc);
        xmlFreeDoc(doc);
        ods_log_error("[%s] unable to create XML RelaxNGs parser context",
           parser_str);
        return ODS_STATUS_XML_ERR;
    }
    /* Parse a schema definition resource and
     * build an internal XML schema structure.
     */
    schema = xmlRelaxNGParse(rngpctx);
    if (schema == NULL) {
        ods_log_error("[%s] unable to parse a schema definition resource",
            parser_str);
        xmlRelaxNGFreeParserCtxt(rngpctx);
        xmlFreeDoc(rngdoc);
        xmlFreeDoc(doc);
        return ODS_STATUS_PARSE_ERR;
    }
    /* Create an XML RelaxNGs validation context. */
    rngctx = xmlRelaxNGNewValidCtxt(schema);
    if (rngctx == NULL) {
        ods_log_error("[%s] unable to create RelaxNGs validation context",
            parser_str);
        xmlRelaxNGFree(schema);
        xmlRelaxNGFreeParserCtxt(rngpctx);
        xmlFreeDoc(rngdoc);
        xmlFreeDoc(doc);
        return ODS_STATUS_RNG_ERR;
    }
    /* Validate a document tree in memory. */
/*
    better not check: if not correct, this will segfault.
    status = xmlRelaxNGValidateDoc(rngctx,doc);
    if (status != 0) {
        ods_log_error("[%s] cfgfile validation failed %s", parser_str,
            cfgfile);
        xmlRelaxNGFreeValidCtxt(rngctx);
        xmlRelaxNGFree(schema);
        xmlRelaxNGFreeParserCtxt(rngpctx);
        xmlFreeDoc(rngdoc);
        xmlFreeDoc(doc);
        return ODS_STATUS_RNG_ERR;
    }
*/
    xmlRelaxNGFreeValidCtxt(rngctx);
    xmlRelaxNGFree(schema);
    xmlRelaxNGFreeParserCtxt(rngpctx);
    xmlFreeDoc(rngdoc);
    xmlFreeDoc(doc);
    return ODS_STATUS_OK;
}
Exemple #11
0
/*
 * call-seq:
 *    XML::Relaxng.new(relaxng_uri) -> relaxng
 * 
 * Create a new relaxng from the specified URI.
 */
VALUE
ruby_xml_relaxng_init_from_uri(VALUE class, VALUE uri) {
  xmlRelaxNGParserCtxtPtr parser;
  ruby_xml_relaxng *relaxng;

  Check_Type(uri, T_STRING);

  parser = xmlRelaxNGNewParserCtxt(StringValuePtr(uri));
  relaxng = ALLOC(ruby_xml_relaxng);
  relaxng->relaxng = xmlRelaxNGParse(parser);
  xmlRelaxNGFreeParserCtxt(parser);

  return Data_Wrap_Struct(cXMLRelaxNG, ruby_xml_relaxng_mark, ruby_xml_relaxng_free, relaxng);
}

/*
 * call-seq:
 *    XML::RelaxNG.document(document) -> relaxng
 * 
 * Create a new relaxng from the specified document.
 */
VALUE
ruby_xml_relaxng_init_from_document(VALUE class, VALUE document) {
  ruby_xml_document_t *rdoc;
  ruby_xml_relaxng *relaxng;
Exemple #12
0
static inline std::auto_ptr<SystemState>
createSystemFromConfig(const char *filename, const XESector *configSector)
{
  uint64_t length = configSector->getLength();
  const scoped_array<char> buf(new char[length + 1]);
  if (!configSector->getData(buf.get())) {
    std::cerr << "Error reading config from \"" << filename << "\"" << std::endl;
    std::exit(1);
  }
  if (length < 8) {
    std::cerr << "Error unexpected config config sector length" << std::endl;
    std::exit(1);
  }
  length -= 8;
  buf[length] = '\0';
  
  /*
   * this initialize the library and check potential ABI mismatches
   * between the version it was compiled for and the actual shared
   * library used.
   */
  LIBXML_TEST_VERSION
  
  xmlDoc *doc = xmlReadDoc((xmlChar*)buf.get(), "config.xml", NULL, 0);

  xmlRelaxNGParserCtxtPtr schemaContext =
    xmlRelaxNGNewMemParserCtxt(configSchema, sizeof(configSchema));
  xmlRelaxNGPtr schema = xmlRelaxNGParse(schemaContext);
  xmlRelaxNGValidCtxtPtr validationContext =
    xmlRelaxNGNewValidCtxt(schema);
  if (xmlRelaxNGValidateDoc(validationContext, doc) != 0) {
    std::exit(1);
  }

  xmlNode *root = xmlDocGetRootElement(doc);
  xmlNode *system = findChild(root, "System");
  xmlNode *nodes = findChild(system, "Nodes");
  std::auto_ptr<SystemState> systemState(new SystemState);
  std::map<long,Node*> nodeNumberMap;
  for (xmlNode *child = nodes->children; child; child = child->next) {
    if (child->type != XML_ELEMENT_NODE ||
        strcmp("Node", (char*)child->name) != 0)
      continue;
    systemState->addNode(createNodeFromConfig(child, nodeNumberMap));
  }
  xmlNode *connections = findChild(system, "Connections");
  for (xmlNode *child = connections->children; child; child = child->next) {
    if (child->type != XML_ELEMENT_NODE ||
        strcmp("SLink", (char*)child->name) != 0)
      continue;
    long nodeID1, link1, nodeID2, link2;
    if (!parseXLinkEnd(findAttribute(child, "end1"), nodeID1, link1)) {
      std::cerr << "Failed to parse \"end1\" attribute" << std::endl;
      std::exit(1);
    }
    if (!parseXLinkEnd(findAttribute(child, "end2"), nodeID2, link2)) {
      std::cerr << "Failed to parse \"end2\" attribute" << std::endl;
      std::exit(1);
    }
    Node *node1 = lookupNodeChecked(nodeNumberMap, nodeID1);
    if (link1 >= node1->getNumXLinks()) {
      std::cerr << "Invalid sLink number " << link1 << std::endl;
      std::exit(1);
    }
    Node *node2 = lookupNodeChecked(nodeNumberMap, nodeID2);
    if (link2 >= node2->getNumXLinks()) {
      std::cerr << "Invalid sLink number " << link2 << std::endl;
      std::exit(1);
    }
    node1->connectXLink(link1, node2, link2);
    node2->connectXLink(link2, node1, link1);
  }
  xmlNode *jtag = findChild(system, "JtagChain");
  unsigned jtagIndex = 0;
  for (xmlNode *child = jtag->children; child; child = child->next) {
    if (child->type != XML_ELEMENT_NODE ||
        strcmp("Node", (char*)child->name) != 0)
      continue;
    long nodeID = readNumberAttribute(child, "id");
    lookupNodeChecked(nodeNumberMap, nodeID)->setJtagIndex(jtagIndex++);
  }
  systemState->finalize();
  xmlFreeDoc(doc);
  xmlCleanupParser();
  return systemState;
}
Exemple #13
0
/* Check an XML file against its rng */
int check_rng(const char *filename, const char *rngfilename) {

	xmlDocPtr doc = NULL;
	xmlDocPtr rngdoc = NULL;
	xmlRelaxNGParserCtxtPtr rngpctx = NULL;
    xmlRelaxNGValidCtxtPtr rngctx = NULL;
    xmlRelaxNGPtr schema = NULL;

	if (verbose) {
		dual_log("DEBUG: About to check XML validity in %s\n", filename);
	}

   	/* Load XML document */
    doc = xmlParseFile(filename);
    if (doc == NULL) {
        dual_log("ERROR: unable to parse file \"%s\"\n", filename);
		/* Maybe the file doesn't exist? */
		check_file(filename, "Configuration file");

        return(1);
    }

    /* Load rng document */
    rngdoc = xmlParseFile(rngfilename);
    if (rngdoc == NULL) {
        dual_log("ERROR: unable to parse file \"%s\"\n", rngfilename);
		/* Maybe the file doesn't exist? */
		check_file(rngfilename, "RNG file");

        xmlFreeDoc(doc);
        
		return(1);
    }

    /* Create an XML RelaxNGs parser context for the relax-ng document. */
    rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
    if (rngpctx == NULL) {
        dual_log("ERROR: unable to create XML RelaxNGs parser context\n");

        xmlFreeDoc(doc);
        xmlFreeDoc(rngdoc);
        
		return(1);
    }

	xmlRelaxNGSetParserErrors(rngpctx,
		(xmlRelaxNGValidityErrorFunc) fprintf,
		(xmlRelaxNGValidityWarningFunc) fprintf,
		stderr);

    /* parse a schema definition resource and build an internal XML Shema struture which can be used to validate instances. */
    schema = xmlRelaxNGParse(rngpctx);
    if (schema == NULL) {
        dual_log("ERROR: unable to parse a schema definition resource\n");

		xmlRelaxNGFreeParserCtxt(rngpctx);
		xmlFreeDoc(doc);
		xmlFreeDoc(rngdoc);

        return(1);
    }

    /* Create an XML RelaxNGs validation context based on the given schema */
    rngctx = xmlRelaxNGNewValidCtxt(schema);
    if (rngctx == NULL) {
        dual_log("ERROR: unable to create RelaxNGs validation context based on the schema\n");

		xmlRelaxNGFree(schema);
		xmlRelaxNGFreeParserCtxt(rngpctx);
		xmlFreeDoc(doc);
		xmlFreeDoc(rngdoc);
        
		return(1);
    }

	xmlRelaxNGSetValidErrors(rngctx,
		(xmlRelaxNGValidityErrorFunc) fprintf,
		(xmlRelaxNGValidityWarningFunc) fprintf,
		stderr);

    /* Validate a document tree in memory. */
    if (xmlRelaxNGValidateDoc(rngctx,doc) != 0) {
        dual_log("ERROR: %s fails to validate\n", filename);

		xmlRelaxNGFreeValidCtxt(rngctx);
		xmlRelaxNGFree(schema);
		xmlRelaxNGFreeParserCtxt(rngpctx);
		xmlFreeDoc(doc);
		xmlFreeDoc(rngdoc);

        return(1);
    }

    xmlRelaxNGFreeValidCtxt(rngctx);
	xmlRelaxNGFree(schema);
    xmlRelaxNGFreeParserCtxt(rngpctx);
    xmlFreeDoc(doc);
    xmlFreeDoc(rngdoc);

	return 0;
}
Exemple #14
0
/**
 *  This is the main function for 'validate' option
 */
int
valMain(int argc, char **argv)
{
    int start;
    static valOptions ops;
    static ErrorInfo errorInfo;
    int invalidFound = 0;
    int options = XML_PARSE_DTDLOAD | XML_PARSE_DTDATTR;

    if (argc <= 2) valUsage(argc, argv, EXIT_BAD_ARGS);
    valInitOptions(&ops);
    start = valParseOptions(&ops, argc, argv);
    if (ops.nonet) options |= XML_PARSE_NONET;

    errorInfo.verbose = ops.err;
    xmlSetStructuredErrorFunc(&errorInfo, reportError);
    xmlLineNumbersDefault(1);

    if (ops.dtd)
    {
        /* xmlReader doesn't work with external dtd, have to use SAX
         * interface */
        int i;

        for (i=start; i<argc; i++)
        {
            xmlDocPtr doc;
            int ret;

            ret = 0;
            doc = NULL;

            errorInfo.filename = argv[i];
            doc = xmlReadFile(argv[i], NULL, options);
            if (doc)
            {
                /* TODO: precompile DTD once */                
                ret = valAgainstDtd(&ops, ops.dtd, doc, argv[i]);
                xmlFreeDoc(doc);
            }
            else
            {
                ret = 1; /* Malformed XML or could not open file */
                if ((ops.listGood < 0) && !ops.show_val_res)
                {
                    fprintf(stdout, "%s\n", argv[i]);
                }
            }
            if (ret) invalidFound = 1;     

            if (ops.show_val_res)
            {
                if (ret == 0)
                    fprintf(stdout, "%s - valid\n", argv[i]);
                else
                    fprintf(stdout, "%s - invalid\n", argv[i]);
            }
        }
    }
    else if (ops.schema || ops.relaxng || ops.embed || ops.wellFormed)
    {
        int i;
        xmlTextReaderPtr reader = NULL;

#ifdef LIBXML_SCHEMAS_ENABLED
        xmlSchemaPtr schema = NULL;
        xmlSchemaParserCtxtPtr schemaParserCtxt = NULL;
        xmlSchemaValidCtxtPtr schemaCtxt = NULL;

        xmlRelaxNGPtr relaxng = NULL;
        xmlRelaxNGParserCtxtPtr relaxngParserCtxt = NULL;
        /* there is no xmlTextReaderRelaxNGValidateCtxt() !?  */

        /* TODO: Do not print debug stuff */
        if (ops.schema)
        {
            schemaParserCtxt = xmlSchemaNewParserCtxt(ops.schema);
            if (!schemaParserCtxt)
            {
                invalidFound = 2;
                goto schemaCleanup;
            }
            errorInfo.filename = ops.schema;
            schema = xmlSchemaParse(schemaParserCtxt);
            if (!schema)
            {
                invalidFound = 2;
                goto schemaCleanup;
            }

            xmlSchemaFreeParserCtxt(schemaParserCtxt);
            schemaCtxt = xmlSchemaNewValidCtxt(schema);
            if (!schemaCtxt)
            {
                invalidFound = 2;
                goto schemaCleanup;
            }

        }
        else if (ops.relaxng)
        {
            relaxngParserCtxt = xmlRelaxNGNewParserCtxt(ops.relaxng);
            if (!relaxngParserCtxt)
            {
                invalidFound = 2;
                goto schemaCleanup;
            }

            errorInfo.filename = ops.relaxng;
            relaxng = xmlRelaxNGParse(relaxngParserCtxt);
            if (!relaxng)
            {
                invalidFound = 2;
                goto schemaCleanup;
            }

        }
#endif  /* LIBXML_SCHEMAS_ENABLED */

        for (i=start; i<argc; i++)
        {
            int ret = 0;
            if (ops.embed) options |= XML_PARSE_DTDVALID;

            if (!reader)
            {
                reader = xmlReaderForFile(argv[i], NULL, options);
            }
            else
            {
                ret = xmlReaderNewFile(reader, argv[i], NULL, options);
            }

            errorInfo.xmlReader = reader;
            errorInfo.filename = argv[i];

            if (reader && ret == 0)
            {
#ifdef LIBXML_SCHEMAS_ENABLED
                if (schemaCtxt)
                {
                    ret = xmlTextReaderSchemaValidateCtxt(reader,
                        schemaCtxt, 0);
                }
                else if (relaxng)
                {
                    ret = xmlTextReaderRelaxNGSetSchema(reader,
                        relaxng);
                }
#endif  /* LIBXML_SCHEMAS_ENABLED */

                if (ret == 0)
                {
                    do
                    {
                        ret = xmlTextReaderRead(reader);
                    } while (ret == 1);
                    if (ret != -1 && (schema || relaxng || ops.embed))
                        ret = !xmlTextReaderIsValid(reader);
                }
            }
            else
            {
                if (ops.err)
                    fprintf(stderr, "couldn't read file '%s'\n", errorInfo.filename);
                ret = 1; /* could not open file */
            }
            if (ret) invalidFound = 1;

            if (!ops.show_val_res)
            {
                if ((ops.listGood > 0) && (ret == 0))
                    fprintf(stdout, "%s\n", argv[i]);
                if ((ops.listGood < 0) && (ret != 0))
                    fprintf(stdout, "%s\n", argv[i]);
            }
            else
            {
                if (ret == 0)
                    fprintf(stdout, "%s - valid\n", argv[i]);
                else
                    fprintf(stdout, "%s - invalid\n", argv[i]);
            }
        }
        errorInfo.xmlReader = NULL;
        xmlFreeTextReader(reader);

#ifdef LIBXML_SCHEMAS_ENABLED
    schemaCleanup:
        xmlSchemaFreeValidCtxt(schemaCtxt);
        xmlRelaxNGFree(relaxng);
        xmlSchemaFree(schema);
        xmlRelaxNGCleanupTypes();
        xmlSchemaCleanupTypes();
#endif  /* LIBXML_SCHEMAS_ENABLED */
    }

    xmlCleanupParser();
    return invalidFound;
}
/**
 * Validation function take first argument as XML type, then check if is
 * well formated. If so, do the same for RNG document. If both success, check
 * XML document against RNG schema restrictions.
 * @return true if pass, false otherwise
 */
Datum
xmlvalidate_rng(PG_FUNCTION_ARGS)
{
#ifdef USE_LIBXML

    text        *data   = NULL;
	char        *rng    = NULL;
	xmlChar     *utf8rng    = NULL;
    xmltype     *xmldata    = NULL;
    char        *xmldataint = NULL;
    xmlChar     *xmldatastr = NULL;
    bool        result  = false;
    int         lenxml  = -1;       // length of xml data
    int         lenrng  = -1;       // length of xsd data
    xmlDocPtr               doc = NULL;
    int ret = -1;

    xmlRelaxNGParserCtxtPtr ctxt    = NULL;
    xmlRelaxNGPtr           schema  = NULL;
    xmlRelaxNGValidCtxtPtr   validctxt = NULL;


    // creating xmlChar * from internal xmltype of stored XML
    xmldata     = PG_GETARG_XML_P(0);
    xmldataint  = VARDATA(xmldata);
    lenxml      = VARSIZE(xmldata) - VARHDRSZ;
    xmldatastr  = (xmlChar *) palloc((lenxml + 1) * sizeof(xmlChar));
	memcpy(xmldatastr, xmldataint, lenxml);
	xmldatastr[lenxml] = '\0';

    // creating xmlChar* from text representation of XSD
    data = PG_GETARG_TEXT_P(1);
	lenrng = VARSIZE(data) - VARHDRSZ;
	rng = text_to_cstring(data);

    //encode XML to internal representation with UTF-8, only one used in LibXML
	utf8rng = pg_do_encoding_conversion((unsigned char*)rng,
										   lenrng,
										   GetDatabaseEncoding(),
										   PG_UTF8);

    //initialize LibXML structures, if allready done -> do nothing
    pg_xml_init();
	xmlInitParser();

    doc = xmlReadMemory((const char *)xmldatastr, lenxml, "include.xml", NULL, 0);

     if (doc == NULL) {
        elog(ERROR, "Failed to parse XML document");
        PG_RETURN_BOOL (false);
    }

    ctxt = xmlRelaxNGNewMemParserCtxt(rng, lenrng);

    if (ctxt == NULL)
    { // unable to create parser context
        elog(ERROR, "Error with creating schema, check if RelaxNG schema is valid");
        PG_RETURN_BOOL (false);
    }

    schema = xmlRelaxNGParse(ctxt);  // parse schema
    xmlRelaxNGFreeParserCtxt(ctxt);  // realease parser context

    validctxt = xmlRelaxNGNewValidCtxt(schema);
    if (validctxt == NULL)
    { // cant create validation context
        xmlRelaxNGFree(schema);
        elog(ERROR, "Cant create validation context");
        PG_RETURN_BOOL (false);
    }

    // set errors to SQL errors
	xmlRelaxNGSetValidErrors(validctxt,
			    xml_error_handler,
			    NULL,
			    0);

    ret = xmlRelaxNGValidateDoc(validctxt, doc);
    if (ret == 0)
    {
        elog(INFO, "Validates");
        result = true;
    } else if (ret > 0)
    {
        elog(INFO, "Dont validates");
        result = false;
    } else
    {
        elog(INFO, "Validation generated an internal error");
        result = false;
    }

    xmlRelaxNGFree(schema);
    xmlRelaxNGFreeValidCtxt(validctxt);

    xmlFreeDoc(doc);    // clean up document in memmory
    xmlCleanupParser(); // clean up stream parser

	PG_RETURN_BOOL (result);
#else
    NO_XML_SUPPORT();
    PG_RETURN_BOOL (false);
#endif
}
int main(int argc, char **argv) {
    int i;
    int files = 0;
    xmlRelaxNGPtr schema = NULL;

    for (i = 1; i < argc ; i++) {
#ifdef LIBXML_DEBUG_ENABLED
	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
	    debug++;
	else
#endif
#ifdef HAVE_SYS_MMAN_H
	if ((!strcmp(argv[i], "-memory")) || (!strcmp(argv[i], "--memory"))) {
	    memory++;
        } else
#endif
	if ((!strcmp(argv[i], "-noout")) || (!strcmp(argv[i], "--noout"))) {
	    noout++;
        } else
	if ((!strcmp(argv[i], "-tree")) || (!strcmp(argv[i], "--tree"))) {
	    tree++;
        }
    }
    xmlLineNumbersDefault(1);
    xmlSubstituteEntitiesDefault(1);
    for (i = 1; i < argc ; i++) {
	if (argv[i][0] != '-') {
	    if (schema == NULL) {
		xmlRelaxNGParserCtxtPtr ctxt;

#ifdef HAVE_SYS_MMAN_H
		if (memory) {
		    int fd;
		    struct stat info;
		    const char *base;
		    if (stat(argv[i], &info) < 0) 
			break;
		    if ((fd = open(argv[i], O_RDONLY)) < 0)
			break;
		    base = mmap(NULL, info.st_size, PROT_READ,
			        MAP_SHARED, fd, 0) ;
		    if (base == (void *) MAP_FAILED)
			break;

		    ctxt = xmlRelaxNGNewMemParserCtxt((char *)base,info.st_size);

		    xmlRelaxNGSetParserErrors(ctxt,
			    (xmlRelaxNGValidityErrorFunc) fprintf,
			    (xmlRelaxNGValidityWarningFunc) fprintf,
			    stderr);
		    schema = xmlRelaxNGParse(ctxt);
		    xmlRelaxNGFreeParserCtxt(ctxt);
		    munmap((char *) base, info.st_size);
		} else
#endif
		{
		    ctxt = xmlRelaxNGNewParserCtxt(argv[i]);
		    xmlRelaxNGSetParserErrors(ctxt,
			    (xmlRelaxNGValidityErrorFunc) fprintf,
			    (xmlRelaxNGValidityWarningFunc) fprintf,
			    stderr);
		    schema = xmlRelaxNGParse(ctxt);
		    xmlRelaxNGFreeParserCtxt(ctxt);
		}
		if (schema == NULL) {
		    printf("Relax-NG schema %s failed to compile\n", argv[i]);
		    files = -1;
		    break;
		}
#ifdef LIBXML_OUTPUT_ENABLED
#ifdef LIBXML_DEBUG_ENABLED
		if (debug)
		    xmlRelaxNGDump(stdout, schema);
#endif
		if (tree)
		    xmlRelaxNGDumpTree(stdout, schema);
#endif /* LIBXML_OUTPUT_ENABLED */
	    } else {
		xmlDocPtr doc;

		doc = xmlReadFile(argv[i],NULL,0);

		if (doc == NULL) {
		    fprintf(stderr, "Could not parse %s\n", argv[i]);
		} else {
		    xmlRelaxNGValidCtxtPtr ctxt;
		    int ret;

		    ctxt = xmlRelaxNGNewValidCtxt(schema);
		    xmlRelaxNGSetValidErrors(ctxt,
			    (xmlRelaxNGValidityErrorFunc) fprintf,
			    (xmlRelaxNGValidityWarningFunc) fprintf,
			    stderr);
		    ret = xmlRelaxNGValidateDoc(ctxt, doc);
		    if (ret == 0) {
			printf("%s validates\n", argv[i]);
		    } else if (ret > 0) {
			printf("%s fails to validate\n", argv[i]);
		    } else {
			printf("%s validation generated an internal error\n",
			       argv[i]);
		    }
		    xmlRelaxNGFreeValidCtxt(ctxt);
		    xmlFreeDoc(doc);
		}
	    }
	    files ++;
	}
    }
    if (schema != NULL)
	xmlRelaxNGFree(schema);
    if (files == 0) {
	printf("Usage : %s [--debug] [--noout] schemas XMLfiles ...\n",
	       argv[0]);
	printf("\tParse the HTML files and output the result of the parsing\n");
#ifdef LIBXML_DEBUG_ENABLED
	printf("\t--debug : dump a debug tree of the in-memory document\n");
#endif
	printf("\t--noout : do not print the result\n");
	printf("\t--tree : print the intermediate Relax-NG document tree\n");
#ifdef HAVE_SYS_MMAN_H
	printf("\t--memory : test the schemas in memory parsing\n");
#endif
    }
    xmlRelaxNGCleanupTypes();
    xmlCleanupParser();
    xmlMemoryDump();

    return(0);
}