| Index: third_party/libxml/src/schematron.c
|
| diff --git a/third_party/libxml/src/schematron.c b/third_party/libxml/src/schematron.c
|
| deleted file mode 100644
|
| index 6200f2d4130a9bc663378b1a278d11d70531db62..0000000000000000000000000000000000000000
|
| --- a/third_party/libxml/src/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 */
|
|
|