more bug fixes, improve the error reporting. second test Daniel

* schematron.c: more bug fixes, improve the error reporting.
* test/schematron/zvon2* result/schematron/zvon2*: second test
Daniel
This commit is contained in:
Daniel Veillard 2005-07-31 13:43:14 +00:00
parent c740a17f45
commit eaecb3eab2
12 changed files with 175 additions and 34 deletions

View File

@ -1,3 +1,8 @@
Sun Jul 31 15:42:31 CEST 2005 Daniel Veillard <daniel@veillard.com>
* schematron.c: more bug fixes, improve the error reporting.
* test/schematron/zvon2* result/schematron/zvon2*: second test
Sun Jul 31 14:15:31 CEST 2005 Daniel Veillard <daniel@veillard.com>
* schematron.c xmllint.c: fixing the loop bug, fixing schematron

View File

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<AAA>
<BBB>bbbb</BBB>
<CCC>cccc</CCC>
</AAA>

View File

@ -0,0 +1,2 @@
Pattern: Character @ forbidden
./test/schematron/zvon2_0.xml validates

View File

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<AAA>
<BBB>bbbb@bbb.com</BBB>
<CCC>ccc@ccc.com</CCC>
</AAA>

View File

@ -0,0 +1,5 @@
Pattern: Character @ forbidden
/AAA line 1: Text in element AAA must not contain character @
/AAA/BBB line 2: Text in element BBB must not contain character @
/AAA/CCC line 3: Text in element CCC must not contain character @
./test/schematron/zvon2_1.xml fails to validate

View File

@ -0,0 +1,6 @@
<?xml version="1.0"?>
<AAA>
<BBB>bbbb</BBB>
<CCC>cccc</CCC>
aaa@aaa.net
</AAA>

View File

@ -0,0 +1,3 @@
Pattern: Character @ forbidden
/AAA line 1: Text in element AAA must not contain character @
./test/schematron/zvon2_2.xml fails to validate

View File

@ -128,7 +128,7 @@ struct _xmlSchematronPattern {
*/
struct _xmlSchematron {
const xmlChar *name; /* schema name */
int preserve; /* was the document preserved by the user */
int preserve; /* was the document passed by the user */
xmlDocPtr doc; /* pointer to the parsed document */
int flags; /* specific to this schematron */
@ -1089,6 +1089,7 @@ xmlSchematronParse(xmlSchematronParserCtxtPtr ctxt)
ctxt->URL, NULL);
return (NULL);
}
ctxt->preserve = 0;
} else if (ctxt->buffer != NULL) {
doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
SCHEMATRON_PARSE_OPTIONS);
@ -1101,9 +1102,11 @@ xmlSchematronParse(xmlSchematronParserCtxtPtr ctxt)
}
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,
@ -1196,6 +1199,9 @@ xmlSchematronParse(xmlSchematronParserCtxtPtr ctxt)
ctxt->URL, NULL);
goto exit;
}
/* the original document must be kept for reporting */
ret->doc = doc;
preserve = 1;
exit:
if (!preserve) {
@ -1234,6 +1240,72 @@ xmlSchematronReportOutput(xmlSchematronValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
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;
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")) {
if ((cur->ns == NULL) || (cur->ns->prefix == NULL))
ret = xmlStrcat(ret, cur->name);
else {
ret = xmlStrcat(ret, cur->ns->prefix);
ret = xmlStrcat(ret, BAD_CAST ":");
ret = xmlStrcat(ret, cur->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
@ -1260,7 +1332,7 @@ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt,
xmlChar *path;
char msg[1000];
long line;
const xmlChar *report;
const xmlChar *report = NULL;
if (((test->type == XML_SCHEMATRON_REPORT) & (!success)) ||
((test->type == XML_SCHEMATRON_ASSERT) & (success)))
@ -1269,15 +1341,25 @@ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt,
path = xmlGetNodePath(cur);
if (path == NULL)
path = (xmlChar *) cur->name;
#if 0
if ((test->report != NULL) && (test->report[0] != 0))
report = test->report;
else if (test->type == XML_SCHEMATRON_ASSERT) {
report = BAD_CAST "node failed assert";
#endif
if (test->node != NULL)
report = xmlSchematronFormatReport(ctxt, test->node, cur);
if (report == NULL) {
if (test->type == XML_SCHEMATRON_ASSERT) {
snprintf(msg, 999, "%s line %ld: node failed assert\n",
(const char *) path, line);
} else {
snprintf(msg, 999, "%s line %ld: node failed report\n",
(const char *) path, line);
}
} else {
report = BAD_CAST "node failed report";
snprintf(msg, 999, "%s line %ld: %s\n", (const char *) path,
line, (const char *) report);
xmlFree(report);
}
snprintf(msg, 999, "%s line %ld: %s\n", (const char *) path,
line, (const char *) report);
xmlSchematronReportOutput(ctxt, cur, &msg[0]);
if ((path != NULL) && (path != (xmlChar *) cur->name))
xmlFree(path);
@ -1436,36 +1518,42 @@ xmlSchematronRunTest(xmlSchematronValidCtxtPtr ctxt,
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))
} 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;
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;
break;
}
xmlXPathFreeObject(ret);
}
if (failed)
if ((failed) && (test->type == XML_SCHEMATRON_ASSERT))
ctxt->nberrors++;
else if ((!failed) && (test->type == XML_SCHEMATRON_REPORT))
ctxt->nberrors++;
xmlSchematronReportSuccess(ctxt, test, cur, !failed);
return(!failed);

View File

@ -0,0 +1,9 @@
<schema xmlns="http://www.ascc.net/xml/schematron" >
<pattern name="Character @ forbidden">
<rule context="*">
<report test="contains(.,'@')">Text in element
<name/> must not contain character @
</report>
</rule>
</pattern>
</schema>

View File

@ -0,0 +1,4 @@
<AAA>
<BBB>bbbb</BBB>
<CCC>cccc</CCC>
</AAA>

View File

@ -0,0 +1,4 @@
<AAA>
<BBB>bbbb@bbb.com</BBB>
<CCC>ccc@ccc.com</CCC>
</AAA>

View File

@ -0,0 +1,5 @@
<AAA>
<BBB>bbbb</BBB>
<CCC>cccc</CCC>
aaa@aaa.net
</AAA>