schematron.c revision 38ae7e4efe803ea78b6499cd05a394db32623e41
/*
* 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
* - 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/xpathInternals.h>
#include <libxml/schematron.h>
#define NEXT_SCHEMATRON(node) \
break; \
}
/**
* TODO:
*
* macro to flag unimplemented blocks
*/
#define TODO \
"Unimplemented block at %s:%d\n", \
typedef enum {
/**
* _xmlSchematronTest:
*
* A Schematrons test, either an assert or a report
*/
typedef struct _xmlSchematronTest xmlSchematronTest;
typedef xmlSchematronTest *xmlSchematronTestPtr;
struct _xmlSchematronTest {
};
/**
* _xmlSchematronRule:
*
* A Schematrons rule
*/
typedef struct _xmlSchematronRule xmlSchematronRule;
typedef xmlSchematronRule *xmlSchematronRulePtr;
struct _xmlSchematronRule {
};
/**
* _xmlSchematronPattern:
*
* A Schematrons pattern
*/
typedef struct _xmlSchematronPattern xmlSchematronPattern;
typedef xmlSchematronPattern *xmlSchematronPatternPtr;
struct _xmlSchematronPattern {
};
/**
* _xmlSchematron:
*
* A Schematrons definition
*/
struct _xmlSchematron {
int preserve; /* was the document passed by the user */
int flags; /* specific to this schematron */
void *_private; /* unused by the library */
int nbNs; /* the number of namespaces */
int nbPattern; /* the number of patterns */
int nbNamespaces; /* number of namespaces in the array */
int maxNamespaces; /* size of the array */
};
/**
* xmlSchematronValidCtxt:
*
* A Schematrons validation context
*/
struct _xmlSchematronValidCtxt {
int type;
int flags; /* an or of xmlSchematronValidOptions */
int nberrors;
int err;
void *ioctx;
};
struct _xmlSchematronParserCtxt {
int type;
int preserve; /* Whether the doc should be freed */
const char *buffer;
int size;
int nberrors;
int err;
int nbNamespaces; /* number of namespaces in the array */
int maxNamespaces; /* size of the array */
int nbIncludes; /* number of includes in the array */
int maxIncludes; /* size of the array */
/* error rreporting data */
void *userData; /* user specific data block */
};
#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
{
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
{
}
}
/**
* xmlSchematronVTypeErrMemory:
* @node: a context node
* @extra: extra informations
*
* Handle an out of memory condition
*/
static void
{
}
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
{
return(NULL);
/*
* try first to compile the test expression
*/
"Failed to compile test expression %s",
return(NULL);
}
return (NULL);
}
} else {
}
return (ret);
}
/**
* xmlSchematronFreeTests:
* @tests: a list of tests
*
* Free a list of tests.
*/
static void
}
}
/**
* 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
{
return(NULL);
/*
* Try first to compile the pattern
*/
ctxt->namespaces);
"Failed to compile context expression %s",
}
return (NULL);
}
} else {
}
} else {
}
return (ret);
}
/**
* xmlSchematronFreeRules:
* @rules: a list of rules
*
* Free a list of rules.
*/
static void
}
}
/**
* 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
{
return(NULL);
return (NULL);
}
} else {
}
return (ret);
}
/**
* xmlSchematronFreePatterns:
* @patterns: a list of patterns
*
* Free a list of patterns.
*/
static void
}
}
/**
* xmlSchematronNewSchematron:
* @ctxt: a schema validation context
*
* Allocate a new Schematron structure.
*
* Returns the newly allocated structure or NULL in case or error
*/
static xmlSchematronPtr
{
return (NULL);
}
return (ret);
}
/**
* xmlSchematronFree:
* @schema: a schema structure
*
* Deallocate a Schematron structure.
*/
void
{
return;
}
/**
* xmlSchematronNewParserCtxt:
* @URL: the location of the schema
*
* to contain an XML Schematrons file.
*
* Returns the parser context or NULL in case of error
*/
xmlSchematronNewParserCtxt(const char *URL)
{
return (NULL);
ret =
xmlMalloc(sizeof(xmlSchematronParserCtxt));
NULL);
return (NULL);
}
NULL);
return (NULL);
}
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
*/
{
return (NULL);
ret =
xmlMalloc(sizeof(xmlSchematronParserCtxt));
NULL);
return (NULL);
}
NULL);
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
*/
{
return (NULL);
ret =
xmlMalloc(sizeof(xmlSchematronParserCtxt));
NULL);
return (NULL);
}
/* The application has responsibility for the document */
NULL);
return (NULL);
}
return (ret);
}
/**
* xmlSchematronFreeParserCtxt:
* @ctxt: the schema parser context
*
* Free the resources associated to the schema parser context
*/
void
{
return;
}
}
#if 0
/**
* xmlSchematronPushInclude:
* @ctxt: the schema parser context
* @doc: the included document
* @cur: the current include node
*
* Add an included document
*/
static void
{
NULL);
return;
}
ctxt->nbIncludes = 0;
tmp = (xmlNodePtr *)
sizeof(xmlNodePtr));
NULL);
return;
}
}
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
{
if (ctxt->nbIncludes <= 0)
return(NULL);
ctxt->nbIncludes--;
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
{
NULL);
return;
}
ctxt->nbNamespaces = 0;
sizeof(const xmlChar *));
NULL);
return;
}
}
ctxt->nbNamespaces++;
}
/**
* xmlSchematronParseRule:
* @ctxt: a schema validation context
* @rule: the rule node
*
* parse a rule element
*/
static void
{
int nbChecks = 0;
"rule has no context attribute",
return;
} else if (context[0] == 0) {
"rule has an empty context attribute",
return;
} else {
return;
}
}
nbChecks++;
"assert has no test attribute",
} else if (test[0] == 0) {
"assert has an empty test attribute",
} else {
/* TODO will need dynamic processing instead */
}
nbChecks++;
"assert has no test attribute",
} else if (test[0] == 0) {
"assert has an empty test attribute",
} else {
/* TODO will need dynamic processing instead */
}
} else {
"Expecting an assert or a report element instead of %s",
}
}
if (nbChecks == 0) {
}
}
/**
* xmlSchematronParsePattern:
* @ctxt: a schema validation context
* @pat: the pattern node
*
* parse a pattern element
*/
static void
{
int nbRules = 0;
}
return;
}
nbRules++;
} else {
}
}
if (nbRules == 0) {
}
}
#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
{
return(NULL);
}
/* do the URI base composition, load and find the root */
"could not load include '%s'.\n",
goto done;
}
"could not find root from include '%s'.\n",
goto done;
}
/* Success, push the include for rollback on exit */
done:
}
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
*/
{
int preserve = 0;
return (NULL);
/*
*/
"xmlSchematronParse: could not load '%s'.\n",
return (NULL);
}
"xmlSchematronParse: could not parse.\n",
return (NULL);
}
preserve = 1;
} else {
"xmlSchematronParse: could not parse.\n",
return (NULL);
}
/*
* Then extract the root and Schematron parse it
*/
if (!preserve) {
}
return (NULL);
}
"The XML document '%s' is not a XML schematron document",
goto exit;
}
goto exit;
/*
* scan the schema elements
*/
}
}
}
}
}
if (uri)
if (prefix)
}
} else {
}
}
"The schematron document '%s' has no pattern",
goto exit;
}
/* the original document must be kept for reporting */
if (preserve) {
}
preserve = 1;
exit:
if (!preserve) {
}
} else {
}
}
return (ret);
}
/************************************************************************
* *
* Schematrontron Reports handler *
* *
************************************************************************/
static xmlNodePtr
return(NULL);
return(NULL);
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
const char *msg) {
/* TODO */
}
/**
* 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 *
return(ret);
}
else {
}
} else {
continue;
}
/*
* remove superfluous \n
*/
xmlChar c;
if (len > 0) {
if ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t')) {
while ((c == ' ') || (c == '\n') ||
(c == '\r') || (c == '\t')) {
len--;
if (len == 0)
break;
}
}
}
}
}
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
return;
/* if quiet and not SVRL report only failures */
return;
} else {
char msg[1000];
long line;
return;
#if 0
#endif
} else {
}
} else {
}
}
}
/**
* xmlSchematronReportPattern:
* @ctxt: the validation context
* @pattern: the current pattern
*
* called from the validation engine when starting to check a pattern
*/
static void
return;
return;
} else {
char msg[1000];
return;
}
}
/************************************************************************
* *
* Validation against a Schematrontron *
* *
************************************************************************/
/**
* 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
*/
{
int i;
NULL);
return (NULL);
}
NULL);
return (NULL);
}
for (i = 0;i < schema->nbNamespaces;i++) {
break;
}
return (ret);
}
/**
* xmlSchematronFreeValidCtxt:
* @ctxt: the schema validation context
*
* Free the resources associated to the schema validation context
*/
void
{
return;
}
static xmlNodePtr
/*
* Do not descend on entities declarations
*/
/*
* Skip DTDs
*/
return(cur);
}
}
return(cur);
}
do {
return(cur);
}
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
{
int failed;
failed = 0;
failed = 1;
} else {
case XPATH_XSLT_TREE:
case XPATH_NODESET:
failed = 1;
break;
case XPATH_BOOLEAN:
break;
case XPATH_NUMBER:
failed = 1;
break;
case XPATH_STRING:
failed = 1;
break;
case XPATH_UNDEFINED:
case XPATH_POINT:
case XPATH_RANGE:
case XPATH_LOCATIONSET:
case XPATH_USERS:
failed = 1;
break;
}
}
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
{
return(-1);
return(1);
}
/*
* we are just trying to assert the validity of the document,
* speed primes over the output, run in a single pass
*/
}
}
}
}
} else {
/*
* Process all contexts one at a time
*/
/*
* 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
*/
}
}
}
}
}
}
}
#ifdef STANDALONE
int
main(void)
{
int ret;
} else {
}
}
}
} else {
}
}
return (0);
}
#endif
#define bottom_schematron
#include "elfgcchack.h"
#endif /* LIBXML_SCHEMATRON_ENABLED */