📄 schematron.c
字号:
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 voidxmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt, xmlSchematronTestPtr test, xmlNodePtr cur, 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) { 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 { snprintf(msg, 999, "%s line %ld: %s\n", (const char *) path, line, (const char *) report); xmlFree((char *) report); } xmlSchematronReportOutput(ctxt, cur, &msg[0]); 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 voidxmlSchematronReportPattern(xmlSchematronValidCtxtPtr ctxt, xmlSchematronPatternPtr pattern) { if ((ctxt == NULL) || (pattern == NULL)) return; if (ctxt->flags & XML_SCHEMATRON_OUT_QUIET) 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 * * * ************************************************************************//** * 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 */xmlSchematronValidCtxtPtrxmlSchematronNewValidCtxt(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 */voidxmlSchematronFreeValidCtxt(xmlSchematronValidCtxtPtr ctxt){ if (ctxt == NULL) return; if (ctxt->xctxt != NULL) xmlXPathFreeContext(ctxt->xctxt); if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); xmlFree(ctxt);}static xmlNodePtrxmlSchematronNextNode(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 intxmlSchematronRunTest(xmlSchematronValidCtxtPtr ctxt, xmlSchematronTestPtr test, xmlDocPtr instance, xmlNodePtr cur){ 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, !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. */intxmlSchematronValidateDoc(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); 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); test = test->next; } } rule = rule->patnext; } cur = xmlSchematronNextNode(cur); } pattern = pattern->next; } } return(ctxt->nberrors);}#ifdef STANDALONEintmain(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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -