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