Blame schematron.c

Packit Service a31ea6
/*
Packit Service a31ea6
 * schematron.c : implementation of the Schematron schema validity checking
Packit Service a31ea6
 *
Packit Service a31ea6
 * See Copyright for the status of this software.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Daniel Veillard <daniel@veillard.com>
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * TODO:
Packit Service a31ea6
 * + double check the semantic, especially
Packit Service a31ea6
 *        - multiple rules applying in a single pattern/node
Packit Service a31ea6
 *        - the semantic of libxml2 patterns vs. XSLT production referenced
Packit Service a31ea6
 *          by the spec.
Packit Service a31ea6
 * + export of results in SVRL
Packit Service a31ea6
 * + full parsing and coverage of the spec, conformance of the input to the
Packit Service a31ea6
 *   spec
Packit Service a31ea6
 * + divergences between the draft and the ISO proposed standard :-(
Packit Service a31ea6
 * + hook and test include
Packit Service a31ea6
 * + try and compare with the XSLT version
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define IN_LIBXML
Packit Service a31ea6
#include "libxml.h"
Packit Service a31ea6
Packit Service a31ea6
#ifdef LIBXML_SCHEMATRON_ENABLED
Packit Service a31ea6
Packit Service a31ea6
#include <string.h>
Packit Service a31ea6
#include <libxml/parser.h>
Packit Service a31ea6
#include <libxml/tree.h>
Packit Service a31ea6
#include <libxml/uri.h>
Packit Service a31ea6
#include <libxml/xpath.h>
Packit Service a31ea6
#include <libxml/xpathInternals.h>
Packit Service a31ea6
#include <libxml/pattern.h>
Packit Service a31ea6
#include <libxml/schematron.h>
Packit Service a31ea6
Packit Service a31ea6
#define SCHEMATRON_PARSE_OPTIONS XML_PARSE_NOENT
Packit Service a31ea6
Packit Service a31ea6
#define SCT_OLD_NS BAD_CAST "http://www.ascc.net/xml/schematron"
Packit Service a31ea6
Packit Service a31ea6
#define XML_SCHEMATRON_NS BAD_CAST "http://purl.oclc.org/dsdl/schematron"
Packit Service a31ea6
Packit Service a31ea6
Packit Service a31ea6
static const xmlChar *xmlSchematronNs = XML_SCHEMATRON_NS;
Packit Service a31ea6
static const xmlChar *xmlOldSchematronNs = SCT_OLD_NS;
Packit Service a31ea6
Packit Service a31ea6
#define IS_SCHEMATRON(node, elem)					\
Packit Service a31ea6
   ((node != NULL) && (node->type == XML_ELEMENT_NODE ) &&		\
Packit Service a31ea6
    (node->ns != NULL) &&						\
Packit Service a31ea6
    (xmlStrEqual(node->name, (const xmlChar *) elem)) &&		\
Packit Service a31ea6
    ((xmlStrEqual(node->ns->href, xmlSchematronNs)) ||			\
Packit Service a31ea6
     (xmlStrEqual(node->ns->href, xmlOldSchematronNs))))
Packit Service a31ea6
Packit Service a31ea6
#define NEXT_SCHEMATRON(node)						\
Packit Service a31ea6
   while (node != NULL) {						\
Packit Service a31ea6
       if ((node->type == XML_ELEMENT_NODE ) && (node->ns != NULL) &&	\
Packit Service a31ea6
           ((xmlStrEqual(node->ns->href, xmlSchematronNs)) ||		\
Packit Service a31ea6
	    (xmlStrEqual(node->ns->href, xmlOldSchematronNs))))		\
Packit Service a31ea6
	   break;							\
Packit Service a31ea6
       node = node->next;						\
Packit Service a31ea6
   }
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * TODO:
Packit Service a31ea6
 *
Packit Service a31ea6
 * macro to flag unimplemented blocks
Packit Service a31ea6
 */
Packit Service a31ea6
#define TODO								\
Packit Service a31ea6
    xmlGenericError(xmlGenericErrorContext,				\
Packit Service a31ea6
	    "Unimplemented block at %s:%d\n",				\
Packit Service a31ea6
            __FILE__, __LINE__);
Packit Service a31ea6
Packit Service a31ea6
typedef enum {
Packit Service a31ea6
    XML_SCHEMATRON_ASSERT=1,
Packit Service a31ea6
    XML_SCHEMATRON_REPORT=2
Packit Service a31ea6
} xmlSchematronTestType;
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * _xmlSchematronTest:
Packit Service a31ea6
 *
Packit Service a31ea6
 * A Schematrons test, either an assert or a report
Packit Service a31ea6
 */
Packit Service a31ea6
typedef struct _xmlSchematronTest xmlSchematronTest;
Packit Service a31ea6
typedef xmlSchematronTest *xmlSchematronTestPtr;
Packit Service a31ea6
struct _xmlSchematronTest {
Packit Service a31ea6
    xmlSchematronTestPtr next;	/* the next test in the list */
Packit Service a31ea6
    xmlSchematronTestType type;	/* the test type */
Packit Service a31ea6
    xmlNodePtr node;		/* the node in the tree */
Packit Service a31ea6
    xmlChar *test;		/* the expression to test */
Packit Service a31ea6
    xmlXPathCompExprPtr comp;	/* the compiled expression */
Packit Service a31ea6
    xmlChar *report;		/* the message to report */
Packit Service a31ea6
};
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * _xmlSchematronRule:
Packit Service a31ea6
 *
Packit Service a31ea6
 * A Schematrons rule
Packit Service a31ea6
 */
Packit Service a31ea6
typedef struct _xmlSchematronRule xmlSchematronRule;
Packit Service a31ea6
typedef xmlSchematronRule *xmlSchematronRulePtr;
Packit Service a31ea6
struct _xmlSchematronRule {
Packit Service a31ea6
    xmlSchematronRulePtr next;	/* the next rule in the list */
Packit Service a31ea6
    xmlSchematronRulePtr patnext;/* the next rule in the pattern list */
Packit Service a31ea6
    xmlNodePtr node;		/* the node in the tree */
Packit Service a31ea6
    xmlChar *context;		/* the context evaluation rule */
Packit Service a31ea6
    xmlSchematronTestPtr tests;	/* the list of tests */
Packit Service a31ea6
    xmlPatternPtr pattern;	/* the compiled pattern associated */
Packit Service a31ea6
    xmlChar *report;		/* the message to report */
Packit Service a31ea6
};
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * _xmlSchematronPattern:
Packit Service a31ea6
 *
Packit Service a31ea6
 * A Schematrons pattern
Packit Service a31ea6
 */
Packit Service a31ea6
typedef struct _xmlSchematronPattern xmlSchematronPattern;
Packit Service a31ea6
typedef xmlSchematronPattern *xmlSchematronPatternPtr;
Packit Service a31ea6
struct _xmlSchematronPattern {
Packit Service a31ea6
    xmlSchematronPatternPtr next;/* the next pattern in the list */
Packit Service a31ea6
    xmlSchematronRulePtr rules;	/* the list of rules */
Packit Service a31ea6
    xmlChar *name;		/* the name of the pattern */
Packit Service a31ea6
};
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * _xmlSchematron:
Packit Service a31ea6
 *
Packit Service a31ea6
 * A Schematrons definition
Packit Service a31ea6
 */
Packit Service a31ea6
struct _xmlSchematron {
Packit Service a31ea6
    const xmlChar *name;	/* schema name */
Packit Service a31ea6
    int preserve;		/* was the document passed by the user */
Packit Service a31ea6
    xmlDocPtr doc;		/* pointer to the parsed document */
Packit Service a31ea6
    int flags;			/* specific to this schematron */
Packit Service a31ea6
Packit Service a31ea6
    void *_private;		/* unused by the library */
Packit Service a31ea6
    xmlDictPtr dict;		/* the dictionary used internally */
Packit Service a31ea6
Packit Service a31ea6
    const xmlChar *title;	/* the title if any */
Packit Service a31ea6
Packit Service a31ea6
    int nbNs;			/* the number of namespaces */
Packit Service a31ea6
Packit Service a31ea6
    int nbPattern;		/* the number of patterns */
Packit Service a31ea6
    xmlSchematronPatternPtr patterns;/* the patterns found */
Packit Service a31ea6
    xmlSchematronRulePtr rules;	/* the rules gathered */
Packit Service a31ea6
    int nbNamespaces;		/* number of namespaces in the array */
Packit Service a31ea6
    int maxNamespaces;		/* size of the array */
Packit Service a31ea6
    const xmlChar **namespaces;	/* the array of namespaces */
Packit Service a31ea6
};
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronValidCtxt:
Packit Service a31ea6
 *
Packit Service a31ea6
 * A Schematrons validation context
Packit Service a31ea6
 */
Packit Service a31ea6
struct _xmlSchematronValidCtxt {
Packit Service a31ea6
    int type;
Packit Service a31ea6
    int flags;			/* an or of xmlSchematronValidOptions */
Packit Service a31ea6
Packit Service a31ea6
    xmlDictPtr dict;
Packit Service a31ea6
    int nberrors;
Packit Service a31ea6
    int err;
Packit Service a31ea6
Packit Service a31ea6
    xmlSchematronPtr schema;
Packit Service a31ea6
    xmlXPathContextPtr xctxt;
Packit Service a31ea6
Packit Service a31ea6
    FILE *outputFile;		/* if using XML_SCHEMATRON_OUT_FILE */
Packit Service a31ea6
    xmlBufferPtr outputBuffer;	/* if using XML_SCHEMATRON_OUT_BUFFER */
Packit Service a31ea6
#ifdef LIBXML_OUTPUT_ENABLED
Packit Service a31ea6
    xmlOutputWriteCallback iowrite; /* if using XML_SCHEMATRON_OUT_IO */
Packit Service a31ea6
    xmlOutputCloseCallback  ioclose;
Packit Service a31ea6
#endif
Packit Service a31ea6
    void *ioctx;
Packit Service a31ea6
Packit Service a31ea6
    /* error reporting data */
Packit Service a31ea6
    void *userData;                      /* user specific data block */
Packit Service a31ea6
    xmlSchematronValidityErrorFunc error;/* the callback in case of errors */
Packit Service a31ea6
    xmlSchematronValidityWarningFunc warning;/* callback in case of warning */
Packit Service a31ea6
    xmlStructuredErrorFunc serror;       /* the structured function */
Packit Service a31ea6
};
Packit Service a31ea6
Packit Service a31ea6
struct _xmlSchematronParserCtxt {
Packit Service a31ea6
    int type;
Packit Service a31ea6
    const xmlChar *URL;
Packit Service a31ea6
    xmlDocPtr doc;
Packit Service a31ea6
    int preserve;               /* Whether the doc should be freed  */
Packit Service a31ea6
    const char *buffer;
Packit Service a31ea6
    int size;
Packit Service a31ea6
Packit Service a31ea6
    xmlDictPtr dict;            /* dictionary for interned string names */
Packit Service a31ea6
Packit Service a31ea6
    int nberrors;
Packit Service a31ea6
    int err;
Packit Service a31ea6
    xmlXPathContextPtr xctxt;	/* the XPath context used for compilation */
Packit Service a31ea6
    xmlSchematronPtr schema;
Packit Service a31ea6
Packit Service a31ea6
    int nbNamespaces;		/* number of namespaces in the array */
Packit Service a31ea6
    int maxNamespaces;		/* size of the array */
Packit Service a31ea6
    const xmlChar **namespaces;	/* the array of namespaces */
Packit Service a31ea6
Packit Service a31ea6
    int nbIncludes;		/* number of includes in the array */
Packit Service a31ea6
    int maxIncludes;		/* size of the array */
Packit Service a31ea6
    xmlNodePtr *includes;	/* the array of includes */
Packit Service a31ea6
Packit Service a31ea6
    /* error reporting data */
Packit Service a31ea6
    void *userData;                      /* user specific data block */
Packit Service a31ea6
    xmlSchematronValidityErrorFunc error;/* the callback in case of errors */
Packit Service a31ea6
    xmlSchematronValidityWarningFunc warning;/* callback in case of warning */
Packit Service a31ea6
    xmlStructuredErrorFunc serror;       /* the structured function */
Packit Service a31ea6
};
Packit Service a31ea6
Packit Service a31ea6
#define XML_STRON_CTXT_PARSER 1
Packit Service a31ea6
#define XML_STRON_CTXT_VALIDATOR 2
Packit Service a31ea6
Packit Service a31ea6
/************************************************************************
Packit Service a31ea6
 *									*
Packit Service a31ea6
 *			Error reporting					*
Packit Service a31ea6
 *									*
Packit Service a31ea6
 ************************************************************************/
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronPErrMemory:
Packit Service a31ea6
 * @node: a context node
Packit Service a31ea6
 * @extra:  extra informations
Packit Service a31ea6
 *
Packit Service a31ea6
 * Handle an out of memory condition
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt,
Packit Service a31ea6
                        const char *extra, xmlNodePtr node)
Packit Service a31ea6
{
Packit Service a31ea6
    if (ctxt != NULL)
Packit Service a31ea6
        ctxt->nberrors++;
Packit Service a31ea6
    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
Packit Service a31ea6
                     extra);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronPErr:
Packit Service a31ea6
 * @ctxt: the parsing context
Packit Service a31ea6
 * @node: the context node
Packit Service a31ea6
 * @error: the error code
Packit Service a31ea6
 * @msg: the error message
Packit Service a31ea6
 * @str1: extra data
Packit Service a31ea6
 * @str2: extra data
Packit Service a31ea6
 *
Packit Service a31ea6
 * Handle a parser error
Packit Service a31ea6
 */
Packit Service a31ea6
static void LIBXML_ATTR_FORMAT(4,0)
Packit Service a31ea6
xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
Packit Service a31ea6
              const char *msg, const xmlChar * str1, const xmlChar * str2)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlGenericErrorFunc channel = NULL;
Packit Service a31ea6
    xmlStructuredErrorFunc schannel = NULL;
Packit Service a31ea6
    void *data = NULL;
Packit Service a31ea6
Packit Service a31ea6
    if (ctxt != NULL) {
Packit Service a31ea6
        ctxt->nberrors++;
Packit Service a31ea6
        channel = ctxt->error;
Packit Service a31ea6
        data = ctxt->userData;
Packit Service a31ea6
	schannel = ctxt->serror;
Packit Service a31ea6
    }
Packit Service a31ea6
    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Packit Service a31ea6
                    error, XML_ERR_ERROR, NULL, 0,
Packit Service a31ea6
                    (const char *) str1, (const char *) str2, NULL, 0, 0,
Packit Service a31ea6
                    msg, str1, str2);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronVTypeErrMemory:
Packit Service a31ea6
 * @node: a context node
Packit Service a31ea6
 * @extra:  extra informations
Packit Service a31ea6
 *
Packit Service a31ea6
 * Handle an out of memory condition
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt,
Packit Service a31ea6
                        const char *extra, xmlNodePtr node)
Packit Service a31ea6
{
Packit Service a31ea6
    if (ctxt != NULL) {
Packit Service a31ea6
        ctxt->nberrors++;
Packit Service a31ea6
        ctxt->err = XML_SCHEMAV_INTERNAL;
Packit Service a31ea6
    }
Packit Service a31ea6
    __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
Packit Service a31ea6
                     extra);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/************************************************************************
Packit Service a31ea6
 *									*
Packit Service a31ea6
 *		Parsing and compilation of the Schematrontrons		*
Packit Service a31ea6
 *									*
Packit Service a31ea6
 ************************************************************************/
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronAddTest:
Packit Service a31ea6
 * @ctxt: the schema parsing context
Packit Service a31ea6
 * @type:  the type of test
Packit Service a31ea6
 * @rule:  the parent rule
Packit Service a31ea6
 * @node:  the node hosting the test
Packit Service a31ea6
 * @test: the associated test
Packit Service a31ea6
 * @report: the associated report string
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add a test to a schematron
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the new pointer or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
static xmlSchematronTestPtr
Packit Service a31ea6
xmlSchematronAddTest(xmlSchematronParserCtxtPtr ctxt,
Packit Service a31ea6
                     xmlSchematronTestType type,
Packit Service a31ea6
                     xmlSchematronRulePtr rule,
Packit Service a31ea6
                     xmlNodePtr node, xmlChar *test, xmlChar *report)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlSchematronTestPtr ret;
Packit Service a31ea6
    xmlXPathCompExprPtr comp;
Packit Service a31ea6
Packit Service a31ea6
    if ((ctxt == NULL) || (rule == NULL) || (node == NULL) ||
Packit Service a31ea6
        (test == NULL))
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * try first to compile the test expression
Packit Service a31ea6
     */
Packit Service a31ea6
    comp = xmlXPathCtxtCompile(ctxt->xctxt, test);
Packit Service a31ea6
    if (comp == NULL) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, node,
Packit Service a31ea6
	    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
	    "Failed to compile test expression %s",
Packit Service a31ea6
	    test, NULL);
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    ret = (xmlSchematronTestPtr) xmlMalloc(sizeof(xmlSchematronTest));
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(ctxt, "allocating schema test", node);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    memset(ret, 0, sizeof(xmlSchematronTest));
Packit Service a31ea6
    ret->type = type;
Packit Service a31ea6
    ret->node = node;
Packit Service a31ea6
    ret->test = test;
Packit Service a31ea6
    ret->comp = comp;
Packit Service a31ea6
    ret->report = report;
Packit Service a31ea6
    ret->next = NULL;
Packit Service a31ea6
    if (rule->tests == NULL) {
Packit Service a31ea6
	rule->tests = ret;
Packit Service a31ea6
    } else {
Packit Service a31ea6
        xmlSchematronTestPtr prev = rule->tests;
Packit Service a31ea6
Packit Service a31ea6
	while (prev->next != NULL)
Packit Service a31ea6
	     prev = prev->next;
Packit Service a31ea6
        prev->next = ret;
Packit Service a31ea6
    }
Packit Service a31ea6
    return (ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronFreeTests:
Packit Service a31ea6
 * @tests:  a list of tests
Packit Service a31ea6
 *
Packit Service a31ea6
 * Free a list of tests.
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronFreeTests(xmlSchematronTestPtr tests) {
Packit Service a31ea6
    xmlSchematronTestPtr next;
Packit Service a31ea6
Packit Service a31ea6
    while (tests != NULL) {
Packit Service a31ea6
        next = tests->next;
Packit Service a31ea6
	if (tests->test != NULL)
Packit Service a31ea6
	    xmlFree(tests->test);
Packit Service a31ea6
	if (tests->comp != NULL)
Packit Service a31ea6
	    xmlXPathFreeCompExpr(tests->comp);
Packit Service a31ea6
	if (tests->report != NULL)
Packit Service a31ea6
	    xmlFree(tests->report);
Packit Service a31ea6
	xmlFree(tests);
Packit Service a31ea6
	tests = next;
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronAddRule:
Packit Service a31ea6
 * @ctxt: the schema parsing context
Packit Service a31ea6
 * @schema:  a schema structure
Packit Service a31ea6
 * @node:  the node hosting the rule
Packit Service a31ea6
 * @context: the associated context string
Packit Service a31ea6
 * @report: the associated report string
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add a rule to a schematron
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the new pointer or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
static xmlSchematronRulePtr
Packit Service a31ea6
xmlSchematronAddRule(xmlSchematronParserCtxtPtr ctxt, xmlSchematronPtr schema,
Packit Service a31ea6
                     xmlSchematronPatternPtr pat, xmlNodePtr node,
Packit Service a31ea6
		     xmlChar *context, xmlChar *report)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlSchematronRulePtr ret;
Packit Service a31ea6
    xmlPatternPtr pattern;
Packit Service a31ea6
Packit Service a31ea6
    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
Packit Service a31ea6
        (context == NULL))
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Try first to compile the pattern
Packit Service a31ea6
     */
Packit Service a31ea6
    pattern = xmlPatterncompile(context, ctxt->dict, XML_PATTERN_XPATH,
Packit Service a31ea6
                                ctxt->namespaces);
Packit Service a31ea6
    if (pattern == NULL) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, node,
Packit Service a31ea6
	    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
	    "Failed to compile context expression %s",
Packit Service a31ea6
	    context, NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    ret = (xmlSchematronRulePtr) xmlMalloc(sizeof(xmlSchematronRule));
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(ctxt, "allocating schema rule", node);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    memset(ret, 0, sizeof(xmlSchematronRule));
Packit Service a31ea6
    ret->node = node;
Packit Service a31ea6
    ret->context = context;
Packit Service a31ea6
    ret->pattern = pattern;
Packit Service a31ea6
    ret->report = report;
Packit Service a31ea6
    ret->next = NULL;
Packit Service a31ea6
    if (schema->rules == NULL) {
Packit Service a31ea6
	schema->rules = ret;
Packit Service a31ea6
    } else {
Packit Service a31ea6
        xmlSchematronRulePtr prev = schema->rules;
Packit Service a31ea6
Packit Service a31ea6
	while (prev->next != NULL)
Packit Service a31ea6
	     prev = prev->next;
Packit Service a31ea6
        prev->next = ret;
Packit Service a31ea6
    }
Packit Service a31ea6
    ret->patnext = NULL;
Packit Service a31ea6
    if (pat->rules == NULL) {
Packit Service a31ea6
	pat->rules = ret;
Packit Service a31ea6
    } else {
Packit Service a31ea6
        xmlSchematronRulePtr prev = pat->rules;
Packit Service a31ea6
Packit Service a31ea6
	while (prev->patnext != NULL)
Packit Service a31ea6
	     prev = prev->patnext;
Packit Service a31ea6
        prev->patnext = ret;
Packit Service a31ea6
    }
Packit Service a31ea6
    return (ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronFreeRules:
Packit Service a31ea6
 * @rules:  a list of rules
Packit Service a31ea6
 *
Packit Service a31ea6
 * Free a list of rules.
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronFreeRules(xmlSchematronRulePtr rules) {
Packit Service a31ea6
    xmlSchematronRulePtr next;
Packit Service a31ea6
Packit Service a31ea6
    while (rules != NULL) {
Packit Service a31ea6
        next = rules->next;
Packit Service a31ea6
	if (rules->tests)
Packit Service a31ea6
	    xmlSchematronFreeTests(rules->tests);
Packit Service a31ea6
	if (rules->context != NULL)
Packit Service a31ea6
	    xmlFree(rules->context);
Packit Service a31ea6
	if (rules->pattern)
Packit Service a31ea6
	    xmlFreePattern(rules->pattern);
Packit Service a31ea6
	if (rules->report != NULL)
Packit Service a31ea6
	    xmlFree(rules->report);
Packit Service a31ea6
	xmlFree(rules);
Packit Service a31ea6
	rules = next;
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronAddPattern:
Packit Service a31ea6
 * @ctxt: the schema parsing context
Packit Service a31ea6
 * @schema:  a schema structure
Packit Service a31ea6
 * @node:  the node hosting the pattern
Packit Service a31ea6
 * @id: the id or name of the pattern
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add a pattern to a schematron
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the new pointer or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
static xmlSchematronPatternPtr
Packit Service a31ea6
xmlSchematronAddPattern(xmlSchematronParserCtxtPtr ctxt,
Packit Service a31ea6
                     xmlSchematronPtr schema, xmlNodePtr node, xmlChar *name)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlSchematronPatternPtr ret;
Packit Service a31ea6
Packit Service a31ea6
    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || (name == NULL))
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    ret = (xmlSchematronPatternPtr) xmlMalloc(sizeof(xmlSchematronPattern));
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(ctxt, "allocating schema pattern", node);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    memset(ret, 0, sizeof(xmlSchematronPattern));
Packit Service a31ea6
    ret->name = name;
Packit Service a31ea6
    ret->next = NULL;
Packit Service a31ea6
    if (schema->patterns == NULL) {
Packit Service a31ea6
	schema->patterns = ret;
Packit Service a31ea6
    } else {
Packit Service a31ea6
        xmlSchematronPatternPtr prev = schema->patterns;
Packit Service a31ea6
Packit Service a31ea6
	while (prev->next != NULL)
Packit Service a31ea6
	     prev = prev->next;
Packit Service a31ea6
        prev->next = ret;
Packit Service a31ea6
    }
Packit Service a31ea6
    return (ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronFreePatterns:
Packit Service a31ea6
 * @patterns:  a list of patterns
Packit Service a31ea6
 *
Packit Service a31ea6
 * Free a list of patterns.
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronFreePatterns(xmlSchematronPatternPtr patterns) {
Packit Service a31ea6
    xmlSchematronPatternPtr next;
Packit Service a31ea6
Packit Service a31ea6
    while (patterns != NULL) {
Packit Service a31ea6
        next = patterns->next;
Packit Service a31ea6
	if (patterns->name != NULL)
Packit Service a31ea6
	    xmlFree(patterns->name);
Packit Service a31ea6
	xmlFree(patterns);
Packit Service a31ea6
	patterns = next;
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronNewSchematron:
Packit Service a31ea6
 * @ctxt:  a schema validation context
Packit Service a31ea6
 *
Packit Service a31ea6
 * Allocate a new Schematron structure.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the newly allocated structure or NULL in case or error
Packit Service a31ea6
 */
Packit Service a31ea6
static xmlSchematronPtr
Packit Service a31ea6
xmlSchematronNewSchematron(xmlSchematronParserCtxtPtr ctxt)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlSchematronPtr ret;
Packit Service a31ea6
Packit Service a31ea6
    ret = (xmlSchematronPtr) xmlMalloc(sizeof(xmlSchematron));
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(ctxt, "allocating schema", NULL);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    memset(ret, 0, sizeof(xmlSchematron));
Packit Service a31ea6
    ret->dict = ctxt->dict;
Packit Service a31ea6
    xmlDictReference(ret->dict);
Packit Service a31ea6
Packit Service a31ea6
    return (ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronFree:
Packit Service a31ea6
 * @schema:  a schema structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * Deallocate a Schematron structure.
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlSchematronFree(xmlSchematronPtr schema)
Packit Service a31ea6
{
Packit Service a31ea6
    if (schema == NULL)
Packit Service a31ea6
        return;
Packit Service a31ea6
Packit Service a31ea6
    if ((schema->doc != NULL) && (!(schema->preserve)))
Packit Service a31ea6
        xmlFreeDoc(schema->doc);
Packit Service a31ea6
Packit Service a31ea6
    if (schema->namespaces != NULL)
Packit Service a31ea6
        xmlFree((char **) schema->namespaces);
Packit Service a31ea6
Packit Service a31ea6
    xmlSchematronFreeRules(schema->rules);
Packit Service a31ea6
    xmlSchematronFreePatterns(schema->patterns);
Packit Service a31ea6
    xmlDictFree(schema->dict);
Packit Service a31ea6
    xmlFree(schema);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronNewParserCtxt:
Packit Service a31ea6
 * @URL:  the location of the schema
Packit Service a31ea6
 *
Packit Service a31ea6
 * Create an XML Schematrons parse context for that file/resource expected
Packit Service a31ea6
 * to contain an XML Schematrons file.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the parser context or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
xmlSchematronParserCtxtPtr
Packit Service a31ea6
xmlSchematronNewParserCtxt(const char *URL)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlSchematronParserCtxtPtr ret;
Packit Service a31ea6
Packit Service a31ea6
    if (URL == NULL)
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
Packit Service a31ea6
    ret =
Packit Service a31ea6
        (xmlSchematronParserCtxtPtr)
Packit Service a31ea6
        xmlMalloc(sizeof(xmlSchematronParserCtxt));
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(NULL, "allocating schema parser context",
Packit Service a31ea6
                                NULL);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    memset(ret, 0, sizeof(xmlSchematronParserCtxt));
Packit Service a31ea6
    ret->type = XML_STRON_CTXT_PARSER;
Packit Service a31ea6
    ret->dict = xmlDictCreate();
Packit Service a31ea6
    ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Packit Service a31ea6
    ret->includes = NULL;
Packit Service a31ea6
    ret->xctxt = xmlXPathNewContext(NULL);
Packit Service a31ea6
    if (ret->xctxt == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
Packit Service a31ea6
                                NULL);
Packit Service a31ea6
	xmlSchematronFreeParserCtxt(ret);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    ret->xctxt->flags = XML_XPATH_CHECKNS;
Packit Service a31ea6
    return (ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronNewMemParserCtxt:
Packit Service a31ea6
 * @buffer:  a pointer to a char array containing the schemas
Packit Service a31ea6
 * @size:  the size of the array
Packit Service a31ea6
 *
Packit Service a31ea6
 * Create an XML Schematrons parse context for that memory buffer expected
Packit Service a31ea6
 * to contain an XML Schematrons file.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the parser context or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
xmlSchematronParserCtxtPtr
Packit Service a31ea6
xmlSchematronNewMemParserCtxt(const char *buffer, int size)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlSchematronParserCtxtPtr ret;
Packit Service a31ea6
Packit Service a31ea6
    if ((buffer == NULL) || (size <= 0))
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
Packit Service a31ea6
    ret =
Packit Service a31ea6
        (xmlSchematronParserCtxtPtr)
Packit Service a31ea6
        xmlMalloc(sizeof(xmlSchematronParserCtxt));
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(NULL, "allocating schema parser context",
Packit Service a31ea6
                                NULL);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    memset(ret, 0, sizeof(xmlSchematronParserCtxt));
Packit Service a31ea6
    ret->buffer = buffer;
Packit Service a31ea6
    ret->size = size;
Packit Service a31ea6
    ret->dict = xmlDictCreate();
Packit Service a31ea6
    ret->xctxt = xmlXPathNewContext(NULL);
Packit Service a31ea6
    if (ret->xctxt == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
Packit Service a31ea6
                                NULL);
Packit Service a31ea6
	xmlSchematronFreeParserCtxt(ret);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    return (ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronNewDocParserCtxt:
Packit Service a31ea6
 * @doc:  a preparsed document tree
Packit Service a31ea6
 *
Packit Service a31ea6
 * Create an XML Schematrons parse context for that document.
Packit Service a31ea6
 * NB. The document may be modified during the parsing process.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the parser context or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
xmlSchematronParserCtxtPtr
Packit Service a31ea6
xmlSchematronNewDocParserCtxt(xmlDocPtr doc)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlSchematronParserCtxtPtr ret;
Packit Service a31ea6
Packit Service a31ea6
    if (doc == NULL)
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
Packit Service a31ea6
    ret =
Packit Service a31ea6
        (xmlSchematronParserCtxtPtr)
Packit Service a31ea6
        xmlMalloc(sizeof(xmlSchematronParserCtxt));
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(NULL, "allocating schema parser context",
Packit Service a31ea6
                                NULL);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    memset(ret, 0, sizeof(xmlSchematronParserCtxt));
Packit Service a31ea6
    ret->doc = doc;
Packit Service a31ea6
    ret->dict = xmlDictCreate();
Packit Service a31ea6
    /* The application has responsibility for the document */
Packit Service a31ea6
    ret->preserve = 1;
Packit Service a31ea6
    ret->xctxt = xmlXPathNewContext(doc);
Packit Service a31ea6
    if (ret->xctxt == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
Packit Service a31ea6
                                NULL);
Packit Service a31ea6
	xmlSchematronFreeParserCtxt(ret);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    return (ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronFreeParserCtxt:
Packit Service a31ea6
 * @ctxt:  the schema parser context
Packit Service a31ea6
 *
Packit Service a31ea6
 * Free the resources associated to the schema parser context
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlSchematronFreeParserCtxt(xmlSchematronParserCtxtPtr ctxt)
Packit Service a31ea6
{
Packit Service a31ea6
    if (ctxt == NULL)
Packit Service a31ea6
        return;
Packit Service a31ea6
    if (ctxt->doc != NULL && !ctxt->preserve)
Packit Service a31ea6
        xmlFreeDoc(ctxt->doc);
Packit Service a31ea6
    if (ctxt->xctxt != NULL) {
Packit Service a31ea6
        xmlXPathFreeContext(ctxt->xctxt);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (ctxt->namespaces != NULL)
Packit Service a31ea6
        xmlFree((char **) ctxt->namespaces);
Packit Service a31ea6
    xmlDictFree(ctxt->dict);
Packit Service a31ea6
    xmlFree(ctxt);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
#if 0
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronPushInclude:
Packit Service a31ea6
 * @ctxt:  the schema parser context
Packit Service a31ea6
 * @doc:  the included document
Packit Service a31ea6
 * @cur:  the current include node
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add an included document
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt,
Packit Service a31ea6
                        xmlDocPtr doc, xmlNodePtr cur)
Packit Service a31ea6
{
Packit Service a31ea6
    if (ctxt->includes == NULL) {
Packit Service a31ea6
        ctxt->maxIncludes = 10;
Packit Service a31ea6
        ctxt->includes = (xmlNodePtr *)
Packit Service a31ea6
	    xmlMalloc(ctxt->maxIncludes * 2 * sizeof(xmlNodePtr));
Packit Service a31ea6
	if (ctxt->includes == NULL) {
Packit Service a31ea6
	    xmlSchematronPErrMemory(NULL, "allocating parser includes",
Packit Service a31ea6
				    NULL);
Packit Service a31ea6
	    return;
Packit Service a31ea6
	}
Packit Service a31ea6
        ctxt->nbIncludes = 0;
Packit Service a31ea6
    } else if (ctxt->nbIncludes + 2 >= ctxt->maxIncludes) {
Packit Service a31ea6
        xmlNodePtr *tmp;
Packit Service a31ea6
Packit Service a31ea6
	tmp = (xmlNodePtr *)
Packit Service a31ea6
	    xmlRealloc(ctxt->includes, ctxt->maxIncludes * 4 *
Packit Service a31ea6
	               sizeof(xmlNodePtr));
Packit Service a31ea6
	if (tmp == NULL) {
Packit Service a31ea6
	    xmlSchematronPErrMemory(NULL, "allocating parser includes",
Packit Service a31ea6
				    NULL);
Packit Service a31ea6
	    return;
Packit Service a31ea6
	}
Packit Service a31ea6
        ctxt->includes = tmp;
Packit Service a31ea6
	ctxt->maxIncludes *= 2;
Packit Service a31ea6
    }
Packit Service a31ea6
    ctxt->includes[2 * ctxt->nbIncludes] = cur;
Packit Service a31ea6
    ctxt->includes[2 * ctxt->nbIncludes + 1] = (xmlNodePtr) doc;
Packit Service a31ea6
    ctxt->nbIncludes++;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronPopInclude:
Packit Service a31ea6
 * @ctxt:  the schema parser context
Packit Service a31ea6
 *
Packit Service a31ea6
 * Pop an include level. The included document is being freed
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the node immediately following the include or NULL if the
Packit Service a31ea6
 *         include list was empty.
Packit Service a31ea6
 */
Packit Service a31ea6
static xmlNodePtr
Packit Service a31ea6
xmlSchematronPopInclude(xmlSchematronParserCtxtPtr ctxt)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlDocPtr doc;
Packit Service a31ea6
    xmlNodePtr ret;
Packit Service a31ea6
Packit Service a31ea6
    if (ctxt->nbIncludes <= 0)
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
    ctxt->nbIncludes--;
Packit Service a31ea6
    doc = (xmlDocPtr) ctxt->includes[2 * ctxt->nbIncludes + 1];
Packit Service a31ea6
    ret = ctxt->includes[2 * ctxt->nbIncludes];
Packit Service a31ea6
    xmlFreeDoc(doc);
Packit Service a31ea6
    if (ret != NULL)
Packit Service a31ea6
	ret = ret->next;
Packit Service a31ea6
    if (ret == NULL)
Packit Service a31ea6
        return(xmlSchematronPopInclude(ctxt));
Packit Service a31ea6
    return(ret);
Packit Service a31ea6
}
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronAddNamespace:
Packit Service a31ea6
 * @ctxt:  the schema parser context
Packit Service a31ea6
 * @prefix:  the namespace prefix
Packit Service a31ea6
 * @ns:  the namespace name
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add a namespace definition in the context
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt,
Packit Service a31ea6
                          const xmlChar *prefix, const xmlChar *ns)
Packit Service a31ea6
{
Packit Service a31ea6
    if (ctxt->namespaces == NULL) {
Packit Service a31ea6
        ctxt->maxNamespaces = 10;
Packit Service a31ea6
        ctxt->namespaces = (const xmlChar **)
Packit Service a31ea6
	    xmlMalloc(ctxt->maxNamespaces * 2 * sizeof(const xmlChar *));
Packit Service a31ea6
	if (ctxt->namespaces == NULL) {
Packit Service a31ea6
	    xmlSchematronPErrMemory(NULL, "allocating parser namespaces",
Packit Service a31ea6
				    NULL);
Packit Service a31ea6
	    return;
Packit Service a31ea6
	}
Packit Service a31ea6
        ctxt->nbNamespaces = 0;
Packit Service a31ea6
    } else if (ctxt->nbNamespaces + 2 >= ctxt->maxNamespaces) {
Packit Service a31ea6
        const xmlChar **tmp;
Packit Service a31ea6
Packit Service a31ea6
	tmp = (const xmlChar **)
Packit Service a31ea6
	    xmlRealloc((xmlChar **) ctxt->namespaces, ctxt->maxNamespaces * 4 *
Packit Service a31ea6
	               sizeof(const xmlChar *));
Packit Service a31ea6
	if (tmp == NULL) {
Packit Service a31ea6
	    xmlSchematronPErrMemory(NULL, "allocating parser namespaces",
Packit Service a31ea6
				    NULL);
Packit Service a31ea6
	    return;
Packit Service a31ea6
	}
Packit Service a31ea6
        ctxt->namespaces = tmp;
Packit Service a31ea6
	ctxt->maxNamespaces *= 2;
Packit Service a31ea6
    }
Packit Service a31ea6
    ctxt->namespaces[2 * ctxt->nbNamespaces] =
Packit Service a31ea6
        xmlDictLookup(ctxt->dict, ns, -1);
Packit Service a31ea6
    ctxt->namespaces[2 * ctxt->nbNamespaces + 1] =
Packit Service a31ea6
        xmlDictLookup(ctxt->dict, prefix, -1);
Packit Service a31ea6
    ctxt->nbNamespaces++;
Packit Service a31ea6
    ctxt->namespaces[2 * ctxt->nbNamespaces] = NULL;
Packit Service a31ea6
    ctxt->namespaces[2 * ctxt->nbNamespaces + 1] = NULL;
Packit Service a31ea6
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronParseRule:
Packit Service a31ea6
 * @ctxt:  a schema validation context
Packit Service a31ea6
 * @rule:  the rule node
Packit Service a31ea6
 *
Packit Service a31ea6
 * parse a rule element
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronParseRule(xmlSchematronParserCtxtPtr ctxt,
Packit Service a31ea6
                       xmlSchematronPatternPtr pattern,
Packit Service a31ea6
		       xmlNodePtr rule)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlNodePtr cur;
Packit Service a31ea6
    int nbChecks = 0;
Packit Service a31ea6
    xmlChar *test;
Packit Service a31ea6
    xmlChar *context;
Packit Service a31ea6
    xmlChar *report;
Packit Service a31ea6
    xmlSchematronRulePtr ruleptr;
Packit Service a31ea6
    xmlSchematronTestPtr testptr;
Packit Service a31ea6
Packit Service a31ea6
    if ((ctxt == NULL) || (rule == NULL)) return;
Packit Service a31ea6
Packit Service a31ea6
    context = xmlGetNoNsProp(rule, BAD_CAST "context");
Packit Service a31ea6
    if (context == NULL) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, rule,
Packit Service a31ea6
	    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
	    "rule has no context attribute",
Packit Service a31ea6
	    NULL, NULL);
Packit Service a31ea6
	return;
Packit Service a31ea6
    } else if (context[0] == 0) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, rule,
Packit Service a31ea6
	    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
	    "rule has an empty context attribute",
Packit Service a31ea6
	    NULL, NULL);
Packit Service a31ea6
	xmlFree(context);
Packit Service a31ea6
	return;
Packit Service a31ea6
    } else {
Packit Service a31ea6
	ruleptr = xmlSchematronAddRule(ctxt, ctxt->schema, pattern,
Packit Service a31ea6
	                               rule, context, NULL);
Packit Service a31ea6
	if (ruleptr == NULL) {
Packit Service a31ea6
	    xmlFree(context);
Packit Service a31ea6
	    return;
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    cur = rule->children;
Packit Service a31ea6
    NEXT_SCHEMATRON(cur);
Packit Service a31ea6
    while (cur != NULL) {
Packit Service a31ea6
	if (IS_SCHEMATRON(cur, "assert")) {
Packit Service a31ea6
	    nbChecks++;
Packit Service a31ea6
	    test = xmlGetNoNsProp(cur, BAD_CAST "test");
Packit Service a31ea6
	    if (test == NULL) {
Packit Service a31ea6
		xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
		    "assert has no test attribute",
Packit Service a31ea6
		    NULL, NULL);
Packit Service a31ea6
	    } else if (test[0] == 0) {
Packit Service a31ea6
		xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
		    "assert has an empty test attribute",
Packit Service a31ea6
		    NULL, NULL);
Packit Service a31ea6
		xmlFree(test);
Packit Service a31ea6
	    } else {
Packit Service a31ea6
		/* TODO will need dynamic processing instead */
Packit Service a31ea6
		report = xmlNodeGetContent(cur);
Packit Service a31ea6
Packit Service a31ea6
		testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_ASSERT,
Packit Service a31ea6
		                               ruleptr, cur, test, report);
Packit Service a31ea6
		if (testptr == NULL)
Packit Service a31ea6
		    xmlFree(test);
Packit Service a31ea6
	    }
Packit Service a31ea6
	} else if (IS_SCHEMATRON(cur, "report")) {
Packit Service a31ea6
	    nbChecks++;
Packit Service a31ea6
	    test = xmlGetNoNsProp(cur, BAD_CAST "test");
Packit Service a31ea6
	    if (test == NULL) {
Packit Service a31ea6
		xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
		    "assert has no test attribute",
Packit Service a31ea6
		    NULL, NULL);
Packit Service a31ea6
	    } else if (test[0] == 0) {
Packit Service a31ea6
		xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
		    "assert has an empty test attribute",
Packit Service a31ea6
		    NULL, NULL);
Packit Service a31ea6
		xmlFree(test);
Packit Service a31ea6
	    } else {
Packit Service a31ea6
		/* TODO will need dynamic processing instead */
Packit Service a31ea6
		report = xmlNodeGetContent(cur);
Packit Service a31ea6
Packit Service a31ea6
		testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_REPORT,
Packit Service a31ea6
		                               ruleptr, cur, test, report);
Packit Service a31ea6
		if (testptr == NULL)
Packit Service a31ea6
		    xmlFree(test);
Packit Service a31ea6
	    }
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		XML_SCHEMAP_NOROOT,
Packit Service a31ea6
		"Expecting an assert or a report element instead of %s",
Packit Service a31ea6
		cur->name, NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
	cur = cur->next;
Packit Service a31ea6
	NEXT_SCHEMATRON(cur);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (nbChecks == 0) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, rule,
Packit Service a31ea6
	    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
	    "rule has no assert nor report element", NULL, NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronParsePattern:
Packit Service a31ea6
 * @ctxt:  a schema validation context
Packit Service a31ea6
 * @pat:  the pattern node
Packit Service a31ea6
 *
Packit Service a31ea6
 * parse a pattern element
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronParsePattern(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr pat)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlNodePtr cur;
Packit Service a31ea6
    xmlSchematronPatternPtr pattern;
Packit Service a31ea6
    int nbRules = 0;
Packit Service a31ea6
    xmlChar *id;
Packit Service a31ea6
Packit Service a31ea6
    if ((ctxt == NULL) || (pat == NULL)) return;
Packit Service a31ea6
Packit Service a31ea6
    id = xmlGetNoNsProp(pat, BAD_CAST "id");
Packit Service a31ea6
    if (id == NULL) {
Packit Service a31ea6
	id = xmlGetNoNsProp(pat, BAD_CAST "name");
Packit Service a31ea6
    }
Packit Service a31ea6
    pattern = xmlSchematronAddPattern(ctxt, ctxt->schema, pat, id);
Packit Service a31ea6
    if (pattern == NULL) {
Packit Service a31ea6
	if (id != NULL)
Packit Service a31ea6
	    xmlFree(id);
Packit Service a31ea6
        return;
Packit Service a31ea6
    }
Packit Service a31ea6
    cur = pat->children;
Packit Service a31ea6
    NEXT_SCHEMATRON(cur);
Packit Service a31ea6
    while (cur != NULL) {
Packit Service a31ea6
	if (IS_SCHEMATRON(cur, "rule")) {
Packit Service a31ea6
	    xmlSchematronParseRule(ctxt, pattern, cur);
Packit Service a31ea6
	    nbRules++;
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		XML_SCHEMAP_NOROOT,
Packit Service a31ea6
		"Expecting a rule element instead of %s", cur->name, NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
	cur = cur->next;
Packit Service a31ea6
	NEXT_SCHEMATRON(cur);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (nbRules == 0) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, pat,
Packit Service a31ea6
	    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
	    "Pattern has no rule element", NULL, NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
#if 0
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronLoadInclude:
Packit Service a31ea6
 * @ctxt:  a schema validation context
Packit Service a31ea6
 * @cur:  the include element
Packit Service a31ea6
 *
Packit Service a31ea6
 * Load the include document, Push the current pointer
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the updated node pointer
Packit Service a31ea6
 */
Packit Service a31ea6
static xmlNodePtr
Packit Service a31ea6
xmlSchematronLoadInclude(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr cur)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlNodePtr ret = NULL;
Packit Service a31ea6
    xmlDocPtr doc = NULL;
Packit Service a31ea6
    xmlChar *href = NULL;
Packit Service a31ea6
    xmlChar *base = NULL;
Packit Service a31ea6
    xmlChar *URI = NULL;
Packit Service a31ea6
Packit Service a31ea6
    if ((ctxt == NULL) || (cur == NULL))
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    href = xmlGetNoNsProp(cur, BAD_CAST "href");
Packit Service a31ea6
    if (href == NULL) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
	    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
	    "Include has no href attribute", NULL, NULL);
Packit Service a31ea6
	return(cur->next);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /* do the URI base composition, load and find the root */
Packit Service a31ea6
    base = xmlNodeGetBase(cur->doc, cur);
Packit Service a31ea6
    URI = xmlBuildURI(href, base);
Packit Service a31ea6
    doc = xmlReadFile((const char *) URI, NULL, SCHEMATRON_PARSE_OPTIONS);
Packit Service a31ea6
    if (doc == NULL) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		      XML_SCHEMAP_FAILED_LOAD,
Packit Service a31ea6
		      "could not load include '%s'.\n",
Packit Service a31ea6
		      URI, NULL);
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    ret = xmlDocGetRootElement(doc);
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		      XML_SCHEMAP_FAILED_LOAD,
Packit Service a31ea6
		      "could not find root from include '%s'.\n",
Packit Service a31ea6
		      URI, NULL);
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /* Success, push the include for rollback on exit */
Packit Service a31ea6
    xmlSchematronPushInclude(ctxt, doc, cur);
Packit Service a31ea6
Packit Service a31ea6
done:
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        if (doc != NULL)
Packit Service a31ea6
	    xmlFreeDoc(doc);
Packit Service a31ea6
    }
Packit Service a31ea6
    xmlFree(href);
Packit Service a31ea6
    if (base != NULL)
Packit Service a31ea6
        xmlFree(base);
Packit Service a31ea6
    if (URI != NULL)
Packit Service a31ea6
        xmlFree(URI);
Packit Service a31ea6
    return(ret);
Packit Service a31ea6
}
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronParse:
Packit Service a31ea6
 * @ctxt:  a schema validation context
Packit Service a31ea6
 *
Packit Service a31ea6
 * parse a schema definition resource and build an internal
Packit Service a31ea6
 * XML Shema struture which can be used to validate instances.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the internal XML Schematron structure built from the resource or
Packit Service a31ea6
 *         NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
xmlSchematronPtr
Packit Service a31ea6
xmlSchematronParse(xmlSchematronParserCtxtPtr ctxt)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlSchematronPtr ret = NULL;
Packit Service a31ea6
    xmlDocPtr doc;
Packit Service a31ea6
    xmlNodePtr root, cur;
Packit Service a31ea6
    int preserve = 0;
Packit Service a31ea6
Packit Service a31ea6
    if (ctxt == NULL)
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
Packit Service a31ea6
    ctxt->nberrors = 0;
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * First step is to parse the input document into an DOM/Infoset
Packit Service a31ea6
     */
Packit Service a31ea6
    if (ctxt->URL != NULL) {
Packit Service a31ea6
        doc = xmlReadFile((const char *) ctxt->URL, NULL,
Packit Service a31ea6
	                  SCHEMATRON_PARSE_OPTIONS);
Packit Service a31ea6
        if (doc == NULL) {
Packit Service a31ea6
	    xmlSchematronPErr(ctxt, NULL,
Packit Service a31ea6
			  XML_SCHEMAP_FAILED_LOAD,
Packit Service a31ea6
                          "xmlSchematronParse: could not load '%s'.\n",
Packit Service a31ea6
                          ctxt->URL, NULL);
Packit Service a31ea6
            return (NULL);
Packit Service a31ea6
        }
Packit Service a31ea6
	ctxt->preserve = 0;
Packit Service a31ea6
    } else if (ctxt->buffer != NULL) {
Packit Service a31ea6
        doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
Packit Service a31ea6
	                    SCHEMATRON_PARSE_OPTIONS);
Packit Service a31ea6
        if (doc == NULL) {
Packit Service a31ea6
	    xmlSchematronPErr(ctxt, NULL,
Packit Service a31ea6
			  XML_SCHEMAP_FAILED_PARSE,
Packit Service a31ea6
                          "xmlSchematronParse: could not parse.\n",
Packit Service a31ea6
                          NULL, NULL);
Packit Service a31ea6
            return (NULL);
Packit Service a31ea6
        }
Packit Service a31ea6
        doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Packit Service a31ea6
        ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Packit Service a31ea6
	ctxt->preserve = 0;
Packit Service a31ea6
    } else if (ctxt->doc != NULL) {
Packit Service a31ea6
        doc = ctxt->doc;
Packit Service a31ea6
	preserve = 1;
Packit Service a31ea6
	ctxt->preserve = 1;
Packit Service a31ea6
    } else {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, NULL,
Packit Service a31ea6
		      XML_SCHEMAP_NOTHING_TO_PARSE,
Packit Service a31ea6
		      "xmlSchematronParse: could not parse.\n",
Packit Service a31ea6
		      NULL, NULL);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Then extract the root and Schematron parse it
Packit Service a31ea6
     */
Packit Service a31ea6
    root = xmlDocGetRootElement(doc);
Packit Service a31ea6
    if (root == NULL) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, (xmlNodePtr) doc,
Packit Service a31ea6
		      XML_SCHEMAP_NOROOT,
Packit Service a31ea6
		      "The schema has no document element.\n", NULL, NULL);
Packit Service a31ea6
	if (!preserve) {
Packit Service a31ea6
	    xmlFreeDoc(doc);
Packit Service a31ea6
	}
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (!IS_SCHEMATRON(root, "schema")) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, root,
Packit Service a31ea6
	    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
	    "The XML document '%s' is not a XML schematron document",
Packit Service a31ea6
	    ctxt->URL, NULL);
Packit Service a31ea6
	goto exit;
Packit Service a31ea6
    }
Packit Service a31ea6
    ret = xmlSchematronNewSchematron(ctxt);
Packit Service a31ea6
    if (ret == NULL)
Packit Service a31ea6
        goto exit;
Packit Service a31ea6
    ctxt->schema = ret;
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * scan the schema elements
Packit Service a31ea6
     */
Packit Service a31ea6
    cur = root->children;
Packit Service a31ea6
    NEXT_SCHEMATRON(cur);
Packit Service a31ea6
    if (IS_SCHEMATRON(cur, "title")) {
Packit Service a31ea6
        xmlChar *title = xmlNodeGetContent(cur);
Packit Service a31ea6
	if (title != NULL) {
Packit Service a31ea6
	    ret->title = xmlDictLookup(ret->dict, title, -1);
Packit Service a31ea6
	    xmlFree(title);
Packit Service a31ea6
	}
Packit Service a31ea6
	cur = cur->next;
Packit Service a31ea6
	NEXT_SCHEMATRON(cur);
Packit Service a31ea6
    }
Packit Service a31ea6
    while (IS_SCHEMATRON(cur, "ns")) {
Packit Service a31ea6
        xmlChar *prefix = xmlGetNoNsProp(cur, BAD_CAST "prefix");
Packit Service a31ea6
        xmlChar *uri = xmlGetNoNsProp(cur, BAD_CAST "uri");
Packit Service a31ea6
	if ((uri == NULL) || (uri[0] == 0)) {
Packit Service a31ea6
	    xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		XML_SCHEMAP_NOROOT,
Packit Service a31ea6
		"ns element has no uri", NULL, NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
	if ((prefix == NULL) || (prefix[0] == 0)) {
Packit Service a31ea6
	    xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		XML_SCHEMAP_NOROOT,
Packit Service a31ea6
		"ns element has no prefix", NULL, NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
	if ((prefix) && (uri)) {
Packit Service a31ea6
	    xmlXPathRegisterNs(ctxt->xctxt, prefix, uri);
Packit Service a31ea6
	    xmlSchematronAddNamespace(ctxt, prefix, uri);
Packit Service a31ea6
	    ret->nbNs++;
Packit Service a31ea6
	}
Packit Service a31ea6
	if (uri)
Packit Service a31ea6
	    xmlFree(uri);
Packit Service a31ea6
	if (prefix)
Packit Service a31ea6
	    xmlFree(prefix);
Packit Service a31ea6
	cur = cur->next;
Packit Service a31ea6
	NEXT_SCHEMATRON(cur);
Packit Service a31ea6
    }
Packit Service a31ea6
    while (cur != NULL) {
Packit Service a31ea6
	if (IS_SCHEMATRON(cur, "pattern")) {
Packit Service a31ea6
	    xmlSchematronParsePattern(ctxt, cur);
Packit Service a31ea6
	    ret->nbPattern++;
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    xmlSchematronPErr(ctxt, cur,
Packit Service a31ea6
		XML_SCHEMAP_NOROOT,
Packit Service a31ea6
		"Expecting a pattern element instead of %s", cur->name, NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
	cur = cur->next;
Packit Service a31ea6
	NEXT_SCHEMATRON(cur);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (ret->nbPattern == 0) {
Packit Service a31ea6
	xmlSchematronPErr(ctxt, root,
Packit Service a31ea6
	    XML_SCHEMAP_NOROOT,
Packit Service a31ea6
	    "The schematron document '%s' has no pattern",
Packit Service a31ea6
	    ctxt->URL, NULL);
Packit Service a31ea6
	goto exit;
Packit Service a31ea6
    }
Packit Service a31ea6
    /* the original document must be kept for reporting */
Packit Service a31ea6
    ret->doc = doc;
Packit Service a31ea6
    if (preserve) {
Packit Service a31ea6
	    ret->preserve = 1;
Packit Service a31ea6
    }
Packit Service a31ea6
    preserve = 1;
Packit Service a31ea6
Packit Service a31ea6
exit:
Packit Service a31ea6
    if (!preserve) {
Packit Service a31ea6
	xmlFreeDoc(doc);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (ret != NULL) {
Packit Service a31ea6
	if (ctxt->nberrors != 0) {
Packit Service a31ea6
	    xmlSchematronFree(ret);
Packit Service a31ea6
	    ret = NULL;
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    ret->namespaces = ctxt->namespaces;
Packit Service a31ea6
	    ret->nbNamespaces = ctxt->nbNamespaces;
Packit Service a31ea6
	    ctxt->namespaces = NULL;
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    return (ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/************************************************************************
Packit Service a31ea6
 *									*
Packit Service a31ea6
 *		Schematrontron Reports handler				*
Packit Service a31ea6
 *									*
Packit Service a31ea6
 ************************************************************************/
Packit Service a31ea6
Packit Service a31ea6
static xmlNodePtr
Packit Service a31ea6
xmlSchematronGetNode(xmlSchematronValidCtxtPtr ctxt,
Packit Service a31ea6
                     xmlNodePtr cur, const xmlChar *xpath) {
Packit Service a31ea6
    xmlNodePtr node = NULL;
Packit Service a31ea6
    xmlXPathObjectPtr ret;
Packit Service a31ea6
Packit Service a31ea6
    if ((ctxt == NULL) || (cur == NULL) || (xpath == NULL))
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    ctxt->xctxt->doc = cur->doc;
Packit Service a31ea6
    ctxt->xctxt->node = cur;
Packit Service a31ea6
    ret = xmlXPathEval(xpath, ctxt->xctxt);
Packit Service a31ea6
    if (ret == NULL)
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    if ((ret->type == XPATH_NODESET) &&
Packit Service a31ea6
        (ret->nodesetval != NULL) && (ret->nodesetval->nodeNr > 0))
Packit Service a31ea6
	node = ret->nodesetval->nodeTab[0];
Packit Service a31ea6
Packit Service a31ea6
    xmlXPathFreeObject(ret);
Packit Service a31ea6
    return(node);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronReportOutput:
Packit Service a31ea6
 * @ctxt: the validation context
Packit Service a31ea6
 * @cur: the current node tested
Packit Service a31ea6
 * @msg: the message output
Packit Service a31ea6
 *
Packit Service a31ea6
 * Output part of the report to whatever channel the user selected
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronReportOutput(xmlSchematronValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Packit Service a31ea6
                          xmlNodePtr cur ATTRIBUTE_UNUSED,
Packit Service a31ea6
                          const char *msg) {
Packit Service a31ea6
    /* TODO */
Packit Service a31ea6
    fprintf(stderr, "%s", msg);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronFormatReport:
Packit Service a31ea6
 * @ctxt:  the validation context
Packit Service a31ea6
 * @test: the test node
Packit Service a31ea6
 * @cur: the current node tested
Packit Service a31ea6
 *
Packit Service a31ea6
 * Build the string being reported to the user.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a report string or NULL in case of error. The string needs
Packit Service a31ea6
 *         to be deallocated by teh caller
Packit Service a31ea6
 */
Packit Service a31ea6
static xmlChar *
Packit Service a31ea6
xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
Packit Service a31ea6
			  xmlNodePtr test, xmlNodePtr cur) {
Packit Service a31ea6
    xmlChar *ret = NULL;
Packit Service a31ea6
    xmlNodePtr child, node;
Packit Service a31ea6
Packit Service a31ea6
    if ((test == NULL) || (cur == NULL))
Packit Service a31ea6
        return(ret);
Packit Service a31ea6
Packit Service a31ea6
    child = test->children;
Packit Service a31ea6
    while (child != NULL) {
Packit Service a31ea6
        if ((child->type == XML_TEXT_NODE) ||
Packit Service a31ea6
	    (child->type == XML_CDATA_SECTION_NODE))
Packit Service a31ea6
	    ret = xmlStrcat(ret, child->content);
Packit Service a31ea6
	else if (IS_SCHEMATRON(child, "name")) {
Packit Service a31ea6
	    xmlChar *path;
Packit Service a31ea6
Packit Service a31ea6
	    path = xmlGetNoNsProp(child, BAD_CAST "path");
Packit Service a31ea6
Packit Service a31ea6
            node = cur;
Packit Service a31ea6
	    if (path != NULL) {
Packit Service a31ea6
	        node = xmlSchematronGetNode(ctxt, cur, path);
Packit Service a31ea6
		if (node == NULL)
Packit Service a31ea6
		    node = cur;
Packit Service a31ea6
		xmlFree(path);
Packit Service a31ea6
	    }
Packit Service a31ea6
Packit Service a31ea6
	    if ((node->ns == NULL) || (node->ns->prefix == NULL))
Packit Service a31ea6
	        ret = xmlStrcat(ret, node->name);
Packit Service a31ea6
	    else {
Packit Service a31ea6
	        ret = xmlStrcat(ret, node->ns->prefix);
Packit Service a31ea6
	        ret = xmlStrcat(ret, BAD_CAST ":");
Packit Service a31ea6
	        ret = xmlStrcat(ret, node->name);
Packit Service a31ea6
	    }
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    child = child->next;
Packit Service a31ea6
	    continue;
Packit Service a31ea6
	}
Packit Service a31ea6
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * remove superfluous \n
Packit Service a31ea6
	 */
Packit Service a31ea6
	if (ret != NULL) {
Packit Service a31ea6
	    int len = xmlStrlen(ret);
Packit Service a31ea6
	    xmlChar c;
Packit Service a31ea6
Packit Service a31ea6
	    if (len > 0) {
Packit Service a31ea6
		c = ret[len - 1];
Packit Service a31ea6
		if ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t')) {
Packit Service a31ea6
		    while ((c == ' ') || (c == '\n') ||
Packit Service a31ea6
		           (c == '\r') || (c == '\t')) {
Packit Service a31ea6
			len--;
Packit Service a31ea6
			if (len == 0)
Packit Service a31ea6
			    break;
Packit Service a31ea6
			c = ret[len - 1];
Packit Service a31ea6
		    }
Packit Service a31ea6
		    ret[len] = ' ';
Packit Service a31ea6
		    ret[len + 1] = 0;
Packit Service a31ea6
		}
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
Packit Service a31ea6
        child = child->next;
Packit Service a31ea6
    }
Packit Service a31ea6
    return(ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronReportSuccess:
Packit Service a31ea6
 * @ctxt:  the validation context
Packit Service a31ea6
 * @test: the compiled test
Packit Service a31ea6
 * @cur: the current node tested
Packit Service a31ea6
 * @success: boolean value for the result
Packit Service a31ea6
 *
Packit Service a31ea6
 * called from the validation engine when an assert or report test have
Packit Service a31ea6
 * been done.
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt,
Packit Service a31ea6
		   xmlSchematronTestPtr test, xmlNodePtr cur, xmlSchematronPatternPtr pattern, int success) {
Packit Service a31ea6
    if ((ctxt == NULL) || (cur == NULL) || (test == NULL))
Packit Service a31ea6
        return;
Packit Service a31ea6
    /* if quiet and not SVRL report only failures */
Packit Service a31ea6
    if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) &&
Packit Service a31ea6
        ((ctxt->flags & XML_SCHEMATRON_OUT_XML) == 0) &&
Packit Service a31ea6
	(test->type == XML_SCHEMATRON_REPORT))
Packit Service a31ea6
        return;
Packit Service a31ea6
    if (ctxt->flags & XML_SCHEMATRON_OUT_XML) {
Packit Service a31ea6
        TODO
Packit Service a31ea6
    } else {
Packit Service a31ea6
        xmlChar *path;
Packit Service a31ea6
	char msg[1000];
Packit Service a31ea6
	long line;
Packit Service a31ea6
	const xmlChar *report = NULL;
Packit Service a31ea6
Packit Service a31ea6
        if (((test->type == XML_SCHEMATRON_REPORT) & (!success)) ||
Packit Service a31ea6
	    ((test->type == XML_SCHEMATRON_ASSERT) & (success)))
Packit Service a31ea6
	    return;
Packit Service a31ea6
	line = xmlGetLineNo(cur);
Packit Service a31ea6
	path = xmlGetNodePath(cur);
Packit Service a31ea6
	if (path == NULL)
Packit Service a31ea6
	    path = (xmlChar *) cur->name;
Packit Service a31ea6
#if 0
Packit Service a31ea6
	if ((test->report != NULL) && (test->report[0] != 0))
Packit Service a31ea6
	    report = test->report;
Packit Service a31ea6
#endif
Packit Service a31ea6
	if (test->node != NULL)
Packit Service a31ea6
            report = xmlSchematronFormatReport(ctxt, test->node, cur);
Packit Service a31ea6
	if (report == NULL) {
Packit Service a31ea6
	    if (test->type == XML_SCHEMATRON_ASSERT) {
Packit Service a31ea6
            report = xmlStrdup((const xmlChar *) "node failed assert");
Packit Service a31ea6
	    } else {
Packit Service a31ea6
            report = xmlStrdup((const xmlChar *) "node failed report");
Packit Service a31ea6
	    }
Packit Service a31ea6
	    }
Packit Service a31ea6
	    snprintf(msg, 999, "%s line %ld: %s\n", (const char *) path,
Packit Service a31ea6
		     line, (const char *) report);
Packit Service a31ea6
Packit Service a31ea6
    if (ctxt->flags & XML_SCHEMATRON_OUT_ERROR) {
Packit Service a31ea6
        xmlStructuredErrorFunc schannel = NULL;
Packit Service a31ea6
        xmlGenericErrorFunc channel = NULL;
Packit Service a31ea6
        void *data = NULL;
Packit Service a31ea6
Packit Service a31ea6
        if (ctxt != NULL) {
Packit Service a31ea6
            if (ctxt->serror != NULL)
Packit Service a31ea6
                schannel = ctxt->serror;
Packit Service a31ea6
            else
Packit Service a31ea6
                channel = ctxt->error;
Packit Service a31ea6
            data = ctxt->userData;
Packit Service a31ea6
	}
Packit Service a31ea6
Packit Service a31ea6
        __xmlRaiseError(schannel, channel, data,
Packit Service a31ea6
                        NULL, cur, XML_FROM_SCHEMATRONV,
Packit Service a31ea6
                        (test->type == XML_SCHEMATRON_ASSERT)?XML_SCHEMATRONV_ASSERT:XML_SCHEMATRONV_REPORT,
Packit Service a31ea6
                        XML_ERR_ERROR, NULL, line,
Packit Service a31ea6
                        (pattern == NULL)?NULL:((const char *) pattern->name),
Packit Service a31ea6
                        (const char *) path,
Packit Service a31ea6
                        (const char *) report, 0, 0,
Packit Service a31ea6
                        "%s", msg);
Packit Service a31ea6
    } else {
Packit Service a31ea6
	xmlSchematronReportOutput(ctxt, cur, &msg[0]);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    xmlFree((char *) report);
Packit Service a31ea6
Packit Service a31ea6
	if ((path != NULL) && (path != (xmlChar *) cur->name))
Packit Service a31ea6
	    xmlFree(path);
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronReportPattern:
Packit Service a31ea6
 * @ctxt:  the validation context
Packit Service a31ea6
 * @pattern: the current pattern
Packit Service a31ea6
 *
Packit Service a31ea6
 * called from the validation engine when starting to check a pattern
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlSchematronReportPattern(xmlSchematronValidCtxtPtr ctxt,
Packit Service a31ea6
			   xmlSchematronPatternPtr pattern) {
Packit Service a31ea6
    if ((ctxt == NULL) || (pattern == NULL))
Packit Service a31ea6
        return;
Packit Service a31ea6
    if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) || (ctxt->flags & XML_SCHEMATRON_OUT_ERROR)) /* Error gives pattern name as part of error */
Packit Service a31ea6
        return;
Packit Service a31ea6
    if (ctxt->flags & XML_SCHEMATRON_OUT_XML) {
Packit Service a31ea6
        TODO
Packit Service a31ea6
    } else {
Packit Service a31ea6
	char msg[1000];
Packit Service a31ea6
Packit Service a31ea6
	if (pattern->name == NULL)
Packit Service a31ea6
	    return;
Packit Service a31ea6
	snprintf(msg, 999, "Pattern: %s\n", (const char *) pattern->name);
Packit Service a31ea6
	xmlSchematronReportOutput(ctxt, NULL, &msg[0]);
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
Packit Service a31ea6
/************************************************************************
Packit Service a31ea6
 *									*
Packit Service a31ea6
 *		Validation against a Schematrontron				*
Packit Service a31ea6
 *									*
Packit Service a31ea6
 ************************************************************************/
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronSetValidStructuredErrors:
Packit Service a31ea6
 * @ctxt:  a Schematron validation context
Packit Service a31ea6
 * @serror:  the structured error function
Packit Service a31ea6
 * @ctx: the functions context
Packit Service a31ea6
 *
Packit Service a31ea6
 * Set the structured error callback
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlSchematronSetValidStructuredErrors(xmlSchematronValidCtxtPtr ctxt,
Packit Service a31ea6
                                      xmlStructuredErrorFunc serror, void *ctx)
Packit Service a31ea6
{
Packit Service a31ea6
    if (ctxt == NULL)
Packit Service a31ea6
        return;
Packit Service a31ea6
    ctxt->serror = serror;
Packit Service a31ea6
    ctxt->error = NULL;
Packit Service a31ea6
    ctxt->warning = NULL;
Packit Service a31ea6
    ctxt->userData = ctx;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronNewValidCtxt:
Packit Service a31ea6
 * @schema:  a precompiled XML Schematrons
Packit Service a31ea6
 * @options: a set of xmlSchematronValidOptions
Packit Service a31ea6
 *
Packit Service a31ea6
 * Create an XML Schematrons validation context based on the given schema.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the validation context or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
xmlSchematronValidCtxtPtr
Packit Service a31ea6
xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options)
Packit Service a31ea6
{
Packit Service a31ea6
    int i;
Packit Service a31ea6
    xmlSchematronValidCtxtPtr ret;
Packit Service a31ea6
Packit Service a31ea6
    ret = (xmlSchematronValidCtxtPtr) xmlMalloc(sizeof(xmlSchematronValidCtxt));
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlSchematronVErrMemory(NULL, "allocating validation context",
Packit Service a31ea6
                                NULL);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    memset(ret, 0, sizeof(xmlSchematronValidCtxt));
Packit Service a31ea6
    ret->type = XML_STRON_CTXT_VALIDATOR;
Packit Service a31ea6
    ret->schema = schema;
Packit Service a31ea6
    ret->xctxt = xmlXPathNewContext(NULL);
Packit Service a31ea6
    ret->flags = options;
Packit Service a31ea6
    if (ret->xctxt == NULL) {
Packit Service a31ea6
        xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
Packit Service a31ea6
                                NULL);
Packit Service a31ea6
	xmlSchematronFreeValidCtxt(ret);
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    for (i = 0;i < schema->nbNamespaces;i++) {
Packit Service a31ea6
        if ((schema->namespaces[2 * i] == NULL) ||
Packit Service a31ea6
            (schema->namespaces[2 * i + 1] == NULL))
Packit Service a31ea6
	    break;
Packit Service a31ea6
	xmlXPathRegisterNs(ret->xctxt, schema->namespaces[2 * i + 1],
Packit Service a31ea6
	                   schema->namespaces[2 * i]);
Packit Service a31ea6
    }
Packit Service a31ea6
    return (ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronFreeValidCtxt:
Packit Service a31ea6
 * @ctxt:  the schema validation context
Packit Service a31ea6
 *
Packit Service a31ea6
 * Free the resources associated to the schema validation context
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlSchematronFreeValidCtxt(xmlSchematronValidCtxtPtr ctxt)
Packit Service a31ea6
{
Packit Service a31ea6
    if (ctxt == NULL)
Packit Service a31ea6
        return;
Packit Service a31ea6
    if (ctxt->xctxt != NULL)
Packit Service a31ea6
        xmlXPathFreeContext(ctxt->xctxt);
Packit Service a31ea6
    if (ctxt->dict != NULL)
Packit Service a31ea6
        xmlDictFree(ctxt->dict);
Packit Service a31ea6
    xmlFree(ctxt);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
static xmlNodePtr
Packit Service a31ea6
xmlSchematronNextNode(xmlNodePtr cur) {
Packit Service a31ea6
    if (cur->children != NULL) {
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * Do not descend on entities declarations
Packit Service a31ea6
	 */
Packit Service a31ea6
	if (cur->children->type != XML_ENTITY_DECL) {
Packit Service a31ea6
	    cur = cur->children;
Packit Service a31ea6
	    /*
Packit Service a31ea6
	     * Skip DTDs
Packit Service a31ea6
	     */
Packit Service a31ea6
	    if (cur->type != XML_DTD_NODE)
Packit Service a31ea6
		return(cur);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    while (cur->next != NULL) {
Packit Service a31ea6
	cur = cur->next;
Packit Service a31ea6
	if ((cur->type != XML_ENTITY_DECL) &&
Packit Service a31ea6
	    (cur->type != XML_DTD_NODE))
Packit Service a31ea6
	    return(cur);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    do {
Packit Service a31ea6
	cur = cur->parent;
Packit Service a31ea6
	if (cur == NULL) break;
Packit Service a31ea6
	if (cur->type == XML_DOCUMENT_NODE) return(NULL);
Packit Service a31ea6
	if (cur->next != NULL) {
Packit Service a31ea6
	    cur = cur->next;
Packit Service a31ea6
	    return(cur);
Packit Service a31ea6
	}
Packit Service a31ea6
    } while (cur != NULL);
Packit Service a31ea6
    return(cur);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronRunTest:
Packit Service a31ea6
 * @ctxt:  the schema validation context
Packit Service a31ea6
 * @test:  the current test
Packit Service a31ea6
 * @instance:  the document instace tree
Packit Service a31ea6
 * @cur:  the current node in the instance
Packit Service a31ea6
 *
Packit Service a31ea6
 * Validate a rule against a tree instance at a given position
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 1 in case of success, 0 if error and -1 in case of internal error
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlSchematronRunTest(xmlSchematronValidCtxtPtr ctxt,
Packit Service a31ea6
     xmlSchematronTestPtr test, xmlDocPtr instance, xmlNodePtr cur, xmlSchematronPatternPtr pattern)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlXPathObjectPtr ret;
Packit Service a31ea6
    int failed;
Packit Service a31ea6
Packit Service a31ea6
    failed = 0;
Packit Service a31ea6
    ctxt->xctxt->doc = instance;
Packit Service a31ea6
    ctxt->xctxt->node = cur;
Packit Service a31ea6
    ret = xmlXPathCompiledEval(test->comp, ctxt->xctxt);
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
	failed = 1;
Packit Service a31ea6
    } else {
Packit Service a31ea6
        switch (ret->type) {
Packit Service a31ea6
	    case XPATH_XSLT_TREE:
Packit Service a31ea6
	    case XPATH_NODESET:
Packit Service a31ea6
		if ((ret->nodesetval == NULL) ||
Packit Service a31ea6
		    (ret->nodesetval->nodeNr == 0))
Packit Service a31ea6
		    failed = 1;
Packit Service a31ea6
		break;
Packit Service a31ea6
	    case XPATH_BOOLEAN:
Packit Service a31ea6
		failed = !ret->boolval;
Packit Service a31ea6
		break;
Packit Service a31ea6
	    case XPATH_NUMBER:
Packit Service a31ea6
		if ((xmlXPathIsNaN(ret->floatval)) ||
Packit Service a31ea6
		    (ret->floatval == 0.0))
Packit Service a31ea6
		    failed = 1;
Packit Service a31ea6
		break;
Packit Service a31ea6
	    case XPATH_STRING:
Packit Service a31ea6
		if ((ret->stringval == NULL) ||
Packit Service a31ea6
		    (ret->stringval[0] == 0))
Packit Service a31ea6
		    failed = 1;
Packit Service a31ea6
		break;
Packit Service a31ea6
	    case XPATH_UNDEFINED:
Packit Service a31ea6
	    case XPATH_POINT:
Packit Service a31ea6
	    case XPATH_RANGE:
Packit Service a31ea6
	    case XPATH_LOCATIONSET:
Packit Service a31ea6
	    case XPATH_USERS:
Packit Service a31ea6
		failed = 1;
Packit Service a31ea6
		break;
Packit Service a31ea6
	}
Packit Service a31ea6
	xmlXPathFreeObject(ret);
Packit Service a31ea6
    }
Packit Service a31ea6
    if ((failed) && (test->type == XML_SCHEMATRON_ASSERT))
Packit Service a31ea6
        ctxt->nberrors++;
Packit Service a31ea6
    else if ((!failed) && (test->type == XML_SCHEMATRON_REPORT))
Packit Service a31ea6
        ctxt->nberrors++;
Packit Service a31ea6
Packit Service a31ea6
    xmlSchematronReportSuccess(ctxt, test, cur, pattern, !failed);
Packit Service a31ea6
Packit Service a31ea6
    return(!failed);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSchematronValidateDoc:
Packit Service a31ea6
 * @ctxt:  the schema validation context
Packit Service a31ea6
 * @instance:  the document instace tree
Packit Service a31ea6
 *
Packit Service a31ea6
 * Validate a tree instance against the schematron
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 in case of success, -1 in case of internal error
Packit Service a31ea6
 *         and an error count otherwise.
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlNodePtr cur, root;
Packit Service a31ea6
    xmlSchematronPatternPtr pattern;
Packit Service a31ea6
    xmlSchematronRulePtr rule;
Packit Service a31ea6
    xmlSchematronTestPtr test;
Packit Service a31ea6
Packit Service a31ea6
    if ((ctxt == NULL) || (ctxt->schema == NULL) ||
Packit Service a31ea6
        (ctxt->schema->rules == NULL) || (instance == NULL))
Packit Service a31ea6
        return(-1);
Packit Service a31ea6
    ctxt->nberrors = 0;
Packit Service a31ea6
    root = xmlDocGetRootElement(instance);
Packit Service a31ea6
    if (root == NULL) {
Packit Service a31ea6
        TODO
Packit Service a31ea6
	ctxt->nberrors++;
Packit Service a31ea6
	return(1);
Packit Service a31ea6
    }
Packit Service a31ea6
    if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) ||
Packit Service a31ea6
        (ctxt->flags == 0)) {
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * we are just trying to assert the validity of the document,
Packit Service a31ea6
	 * speed primes over the output, run in a single pass
Packit Service a31ea6
	 */
Packit Service a31ea6
	cur = root;
Packit Service a31ea6
	while (cur != NULL) {
Packit Service a31ea6
	    rule = ctxt->schema->rules;
Packit Service a31ea6
	    while (rule != NULL) {
Packit Service a31ea6
		if (xmlPatternMatch(rule->pattern, cur) == 1) {
Packit Service a31ea6
		    test = rule->tests;
Packit Service a31ea6
		    while (test != NULL) {
Packit Service a31ea6
			xmlSchematronRunTest(ctxt, test, instance, cur, (xmlSchematronPatternPtr)rule->pattern);
Packit Service a31ea6
			test = test->next;
Packit Service a31ea6
		    }
Packit Service a31ea6
		}
Packit Service a31ea6
		rule = rule->next;
Packit Service a31ea6
	    }
Packit Service a31ea6
Packit Service a31ea6
	    cur = xmlSchematronNextNode(cur);
Packit Service a31ea6
	}
Packit Service a31ea6
    } else {
Packit Service a31ea6
        /*
Packit Service a31ea6
	 * Process all contexts one at a time
Packit Service a31ea6
	 */
Packit Service a31ea6
	pattern = ctxt->schema->patterns;
Packit Service a31ea6
Packit Service a31ea6
	while (pattern != NULL) {
Packit Service a31ea6
	    xmlSchematronReportPattern(ctxt, pattern);
Packit Service a31ea6
Packit Service a31ea6
	    /*
Packit Service a31ea6
	     * TODO convert the pattern rule to a direct XPath and
Packit Service a31ea6
	     * compute directly instead of using the pattern matching
Packit Service a31ea6
	     * over the full document...
Packit Service a31ea6
	     * Check the exact semantic
Packit Service a31ea6
	     */
Packit Service a31ea6
	    cur = root;
Packit Service a31ea6
	    while (cur != NULL) {
Packit Service a31ea6
		rule = pattern->rules;
Packit Service a31ea6
		while (rule != NULL) {
Packit Service a31ea6
		    if (xmlPatternMatch(rule->pattern, cur) == 1) {
Packit Service a31ea6
			test = rule->tests;
Packit Service a31ea6
			while (test != NULL) {
Packit Service a31ea6
			    xmlSchematronRunTest(ctxt, test, instance, cur, pattern);
Packit Service a31ea6
			    test = test->next;
Packit Service a31ea6
			}
Packit Service a31ea6
		    }
Packit Service a31ea6
		    rule = rule->patnext;
Packit Service a31ea6
		}
Packit Service a31ea6
Packit Service a31ea6
		cur = xmlSchematronNextNode(cur);
Packit Service a31ea6
	    }
Packit Service a31ea6
	    pattern = pattern->next;
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    return(ctxt->nberrors);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
#ifdef STANDALONE
Packit Service a31ea6
int
Packit Service a31ea6
main(void)
Packit Service a31ea6
{
Packit Service a31ea6
    int ret;
Packit Service a31ea6
    xmlDocPtr instance;
Packit Service a31ea6
    xmlSchematronParserCtxtPtr pctxt;
Packit Service a31ea6
    xmlSchematronValidCtxtPtr vctxt;
Packit Service a31ea6
    xmlSchematronPtr schema = NULL;
Packit Service a31ea6
Packit Service a31ea6
    pctxt = xmlSchematronNewParserCtxt("tst.sct");
Packit Service a31ea6
    if (pctxt == NULL) {
Packit Service a31ea6
        fprintf(stderr, "failed to build schematron parser\n");
Packit Service a31ea6
    } else {
Packit Service a31ea6
        schema = xmlSchematronParse(pctxt);
Packit Service a31ea6
	if (schema == NULL) {
Packit Service a31ea6
	    fprintf(stderr, "failed to compile schematron\n");
Packit Service a31ea6
	}
Packit Service a31ea6
	xmlSchematronFreeParserCtxt(pctxt);
Packit Service a31ea6
    }
Packit Service a31ea6
    instance = xmlReadFile("tst.sct", NULL,
Packit Service a31ea6
                           XML_PARSE_NOENT | XML_PARSE_NOCDATA);
Packit Service a31ea6
    if (instance == NULL) {
Packit Service a31ea6
	fprintf(stderr, "failed to parse instance\n");
Packit Service a31ea6
    }
Packit Service a31ea6
    if ((schema != NULL) && (instance != NULL)) {
Packit Service a31ea6
        vctxt = xmlSchematronNewValidCtxt(schema);
Packit Service a31ea6
	if (vctxt == NULL) {
Packit Service a31ea6
	    fprintf(stderr, "failed to build schematron validator\n");
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    ret = xmlSchematronValidateDoc(vctxt, instance);
Packit Service a31ea6
	    xmlSchematronFreeValidCtxt(vctxt);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    xmlSchematronFree(schema);
Packit Service a31ea6
    xmlFreeDoc(instance);
Packit Service a31ea6
Packit Service a31ea6
    xmlCleanupParser();
Packit Service a31ea6
    xmlMemoryDump();
Packit Service a31ea6
Packit Service a31ea6
    return (0);
Packit Service a31ea6
}
Packit Service a31ea6
#endif
Packit Service a31ea6
#define bottom_schematron
Packit Service a31ea6
#include "elfgcchack.h"
Packit Service a31ea6
#endif /* LIBXML_SCHEMATRON_ENABLED */