mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-03-21 22:50:08 +03:00
schematron: Improve error handling
Implement xmlSchematronVErr. Handle malloc failure from xmlRaiseError. Stop using xmlGenericError. Remove argument from memory error handler. Use xmlRaiseMemoryError. Remove TODO macro.
This commit is contained in:
parent
83c6aeef49
commit
664db89e0e
198
schematron.c
198
schematron.c
@ -63,16 +63,6 @@ static const xmlChar *xmlOldSchematronNs = SCT_OLD_NS;
|
||||
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
|
||||
@ -242,13 +232,11 @@ struct _xmlSchematronParserCtxt {
|
||||
* Handle an out of memory condition
|
||||
*/
|
||||
static void
|
||||
xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt,
|
||||
const char *extra, xmlNodePtr node)
|
||||
xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt)
|
||||
{
|
||||
if (ctxt != NULL)
|
||||
ctxt->nberrors++;
|
||||
__xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
|
||||
extra);
|
||||
xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_SCHEMASP, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -269,6 +257,7 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
|
||||
xmlGenericErrorFunc channel = NULL;
|
||||
xmlStructuredErrorFunc schannel = NULL;
|
||||
void *data = NULL;
|
||||
int res;
|
||||
|
||||
if (ctxt != NULL) {
|
||||
ctxt->nberrors++;
|
||||
@ -276,10 +265,13 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int 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);
|
||||
|
||||
res = __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);
|
||||
if (res < 0)
|
||||
xmlSchematronPErrMemory(ctxt);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -290,15 +282,48 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
|
||||
* Handle an out of memory condition
|
||||
*/
|
||||
static void
|
||||
xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt,
|
||||
const char *extra, xmlNodePtr node)
|
||||
xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt)
|
||||
{
|
||||
if (ctxt != NULL) {
|
||||
ctxt->nberrors++;
|
||||
ctxt->err = XML_SCHEMAV_INTERNAL;
|
||||
}
|
||||
__xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
|
||||
extra);
|
||||
xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_SCHEMASV, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSchematronVErr:
|
||||
* @ctxt: the parsing context
|
||||
* @node: the context node
|
||||
* @error: the error code
|
||||
* @msg: the error message
|
||||
* @str1: extra data
|
||||
* @str2: extra data
|
||||
*
|
||||
* Handle a validation error
|
||||
*/
|
||||
static void LIBXML_ATTR_FORMAT(3,0)
|
||||
xmlSchematronVErr(xmlSchematronValidCtxtPtr ctxt, int error,
|
||||
const char *msg, const xmlChar * str1)
|
||||
{
|
||||
xmlGenericErrorFunc channel = NULL;
|
||||
xmlStructuredErrorFunc schannel = NULL;
|
||||
void *data = NULL;
|
||||
int res;
|
||||
|
||||
if (ctxt != NULL) {
|
||||
ctxt->nberrors++;
|
||||
channel = ctxt->error;
|
||||
data = ctxt->userData;
|
||||
schannel = ctxt->serror;
|
||||
}
|
||||
|
||||
res = __xmlRaiseError(schannel, channel, data, ctxt, NULL,
|
||||
XML_FROM_SCHEMASV, error, XML_ERR_ERROR, NULL, 0,
|
||||
(const char *) str1, NULL, NULL, 0, 0,
|
||||
msg, str1);
|
||||
if (res < 0)
|
||||
xmlSchematronVErrMemory(ctxt);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -347,7 +372,7 @@ xmlSchematronAddTest(xmlSchematronParserCtxtPtr ctxt,
|
||||
|
||||
ret = (xmlSchematronTestPtr) xmlMalloc(sizeof(xmlSchematronTest));
|
||||
if (ret == NULL) {
|
||||
xmlSchematronPErrMemory(ctxt, "allocating schema test", node);
|
||||
xmlSchematronPErrMemory(ctxt);
|
||||
return (NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(xmlSchematronTest));
|
||||
@ -451,7 +476,7 @@ xmlSchematronAddRule(xmlSchematronParserCtxtPtr ctxt, xmlSchematronPtr schema,
|
||||
|
||||
ret = (xmlSchematronRulePtr) xmlMalloc(sizeof(xmlSchematronRule));
|
||||
if (ret == NULL) {
|
||||
xmlSchematronPErrMemory(ctxt, "allocating schema rule", node);
|
||||
xmlSchematronPErrMemory(ctxt);
|
||||
return (NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(xmlSchematronRule));
|
||||
@ -532,7 +557,7 @@ xmlSchematronAddPattern(xmlSchematronParserCtxtPtr ctxt,
|
||||
|
||||
ret = (xmlSchematronPatternPtr) xmlMalloc(sizeof(xmlSchematronPattern));
|
||||
if (ret == NULL) {
|
||||
xmlSchematronPErrMemory(ctxt, "allocating schema pattern", node);
|
||||
xmlSchematronPErrMemory(ctxt);
|
||||
return (NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(xmlSchematronPattern));
|
||||
@ -584,7 +609,7 @@ xmlSchematronNewSchematron(xmlSchematronParserCtxtPtr ctxt)
|
||||
|
||||
ret = (xmlSchematronPtr) xmlMalloc(sizeof(xmlSchematron));
|
||||
if (ret == NULL) {
|
||||
xmlSchematronPErrMemory(ctxt, "allocating schema", NULL);
|
||||
xmlSchematronPErrMemory(ctxt);
|
||||
return (NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(xmlSchematron));
|
||||
@ -639,8 +664,7 @@ xmlSchematronNewParserCtxt(const char *URL)
|
||||
(xmlSchematronParserCtxtPtr)
|
||||
xmlMalloc(sizeof(xmlSchematronParserCtxt));
|
||||
if (ret == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating schema parser context",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
return (NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(xmlSchematronParserCtxt));
|
||||
@ -650,8 +674,7 @@ xmlSchematronNewParserCtxt(const char *URL)
|
||||
ret->includes = NULL;
|
||||
ret->xctxt = xmlXPathNewContext(NULL);
|
||||
if (ret->xctxt == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
xmlSchematronFreeParserCtxt(ret);
|
||||
return (NULL);
|
||||
}
|
||||
@ -681,8 +704,7 @@ xmlSchematronNewMemParserCtxt(const char *buffer, int size)
|
||||
(xmlSchematronParserCtxtPtr)
|
||||
xmlMalloc(sizeof(xmlSchematronParserCtxt));
|
||||
if (ret == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating schema parser context",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
return (NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(xmlSchematronParserCtxt));
|
||||
@ -691,8 +713,7 @@ xmlSchematronNewMemParserCtxt(const char *buffer, int size)
|
||||
ret->dict = xmlDictCreate();
|
||||
ret->xctxt = xmlXPathNewContext(NULL);
|
||||
if (ret->xctxt == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
xmlSchematronFreeParserCtxt(ret);
|
||||
return (NULL);
|
||||
}
|
||||
@ -720,8 +741,7 @@ xmlSchematronNewDocParserCtxt(xmlDocPtr doc)
|
||||
(xmlSchematronParserCtxtPtr)
|
||||
xmlMalloc(sizeof(xmlSchematronParserCtxt));
|
||||
if (ret == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating schema parser context",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
return (NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(xmlSchematronParserCtxt));
|
||||
@ -731,8 +751,7 @@ xmlSchematronNewDocParserCtxt(xmlDocPtr doc)
|
||||
ret->preserve = 1;
|
||||
ret->xctxt = xmlXPathNewContext(doc);
|
||||
if (ret->xctxt == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
xmlSchematronFreeParserCtxt(ret);
|
||||
return (NULL);
|
||||
}
|
||||
@ -780,8 +799,7 @@ xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt,
|
||||
ctxt->includes = (xmlNodePtr *)
|
||||
xmlMalloc(ctxt->maxIncludes * 2 * sizeof(xmlNodePtr));
|
||||
if (ctxt->includes == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating parser includes",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
return;
|
||||
}
|
||||
ctxt->nbIncludes = 0;
|
||||
@ -792,8 +810,7 @@ xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt,
|
||||
xmlRealloc(ctxt->includes, ctxt->maxIncludes * 4 *
|
||||
sizeof(xmlNodePtr));
|
||||
if (tmp == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating parser includes",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
return;
|
||||
}
|
||||
ctxt->includes = tmp;
|
||||
@ -850,8 +867,7 @@ xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt,
|
||||
ctxt->namespaces = (const xmlChar **)
|
||||
xmlMalloc(ctxt->maxNamespaces * 2 * sizeof(const xmlChar *));
|
||||
if (ctxt->namespaces == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating parser namespaces",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
return;
|
||||
}
|
||||
ctxt->nbNamespaces = 0;
|
||||
@ -862,8 +878,7 @@ xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt,
|
||||
xmlRealloc((xmlChar **) ctxt->namespaces, ctxt->maxNamespaces * 4 *
|
||||
sizeof(const xmlChar *));
|
||||
if (tmp == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating parser namespaces",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
return;
|
||||
}
|
||||
ctxt->namespaces = tmp;
|
||||
@ -1493,9 +1508,6 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
|
||||
ret = xmlStrcat(ret, spacer);
|
||||
ret = xmlStrcat(ret, eval->nodesetval->nodeTab[indx]->name);
|
||||
}
|
||||
} else {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"Empty node set\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1521,8 +1533,8 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
|
||||
ret = xmlStrcat(ret, eval->stringval);
|
||||
break;
|
||||
default:
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"Unsupported XPATH Type: %d\n", eval->type);
|
||||
xmlSchematronVErr(ctxt, XML_ERR_INTERNAL_ERROR,
|
||||
"Unsupported XPATH Type\n", NULL);
|
||||
}
|
||||
xmlXPathFreeObject(eval);
|
||||
xmlXPathFreeCompExpr(comp);
|
||||
@ -1581,7 +1593,7 @@ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt,
|
||||
(test->type == XML_SCHEMATRON_REPORT))
|
||||
return;
|
||||
if (ctxt->flags & XML_SCHEMATRON_OUT_XML) {
|
||||
TODO
|
||||
/* TODO */
|
||||
} else {
|
||||
xmlChar *path;
|
||||
char msg[1000];
|
||||
@ -1612,26 +1624,28 @@ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt,
|
||||
line, (const char *) report);
|
||||
|
||||
if (ctxt->flags & XML_SCHEMATRON_OUT_ERROR) {
|
||||
xmlStructuredErrorFunc schannel = NULL;
|
||||
xmlGenericErrorFunc channel = NULL;
|
||||
void *data = NULL;
|
||||
xmlStructuredErrorFunc schannel;
|
||||
xmlGenericErrorFunc channel;
|
||||
void *data;
|
||||
int res;
|
||||
|
||||
if (ctxt != NULL) {
|
||||
if (ctxt->serror != NULL)
|
||||
schannel = ctxt->serror;
|
||||
else
|
||||
channel = ctxt->error;
|
||||
data = ctxt->userData;
|
||||
}
|
||||
schannel = ctxt->serror;
|
||||
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);
|
||||
res = __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);
|
||||
if (res < 0)
|
||||
xmlSchematronVErrMemory(ctxt);
|
||||
} else {
|
||||
xmlSchematronReportOutput(ctxt, cur, &msg[0]);
|
||||
}
|
||||
@ -1658,7 +1672,7 @@ xmlSchematronReportPattern(xmlSchematronValidCtxtPtr ctxt,
|
||||
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
|
||||
/* TODO */
|
||||
} else {
|
||||
char msg[1000];
|
||||
|
||||
@ -1713,8 +1727,7 @@ xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options)
|
||||
|
||||
ret = (xmlSchematronValidCtxtPtr) xmlMalloc(sizeof(xmlSchematronValidCtxt));
|
||||
if (ret == NULL) {
|
||||
xmlSchematronVErrMemory(NULL, "allocating validation context",
|
||||
NULL);
|
||||
xmlSchematronVErrMemory(NULL);
|
||||
return (NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(xmlSchematronValidCtxt));
|
||||
@ -1723,8 +1736,7 @@ xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options)
|
||||
ret->xctxt = xmlXPathNewContext(NULL);
|
||||
ret->flags = options;
|
||||
if (ret->xctxt == NULL) {
|
||||
xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context",
|
||||
NULL);
|
||||
xmlSchematronPErrMemory(NULL);
|
||||
xmlSchematronFreeValidCtxt(ret);
|
||||
return (NULL);
|
||||
}
|
||||
@ -1870,7 +1882,9 @@ xmlSchematronRunTest(xmlSchematronValidCtxtPtr ctxt,
|
||||
* Returns -1 in case of errors, otherwise 0
|
||||
*/
|
||||
static int
|
||||
xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let,
|
||||
xmlSchematronRegisterVariables(xmlSchematronValidCtxtPtr vctxt,
|
||||
xmlXPathContextPtr ctxt,
|
||||
xmlSchematronLetPtr let,
|
||||
xmlDocPtr instance, xmlNodePtr cur)
|
||||
{
|
||||
xmlXPathObjectPtr let_eval;
|
||||
@ -1880,13 +1894,14 @@ xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let,
|
||||
while (let != NULL) {
|
||||
let_eval = xmlXPathCompiledEval(let->comp, ctxt);
|
||||
if (let_eval == NULL) {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"Evaluation of compiled expression failed\n");
|
||||
xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR,
|
||||
"Evaluation of compiled expression failed\n",
|
||||
NULL);
|
||||
return -1;
|
||||
}
|
||||
if(xmlXPathRegisterVariableNS(ctxt, let->name, NULL, let_eval)) {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"Registering a let variable failed\n");
|
||||
xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR,
|
||||
"Registering a let variable failed\n", NULL);
|
||||
return -1;
|
||||
}
|
||||
let = let->next;
|
||||
@ -1904,12 +1919,14 @@ xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let,
|
||||
* Returns -1 in case of errors, otherwise 0
|
||||
*/
|
||||
static int
|
||||
xmlSchematronUnregisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let)
|
||||
xmlSchematronUnregisterVariables(xmlSchematronValidCtxtPtr vctxt,
|
||||
xmlXPathContextPtr ctxt,
|
||||
xmlSchematronLetPtr let)
|
||||
{
|
||||
while (let != NULL) {
|
||||
if (xmlXPathRegisterVariableNS(ctxt, let->name, NULL, NULL)) {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"Unregistering a let variable failed\n");
|
||||
xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR,
|
||||
"Unregistering a let variable failed\n", NULL);
|
||||
return -1;
|
||||
}
|
||||
let = let->next;
|
||||
@ -1941,7 +1958,7 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
|
||||
ctxt->nberrors = 0;
|
||||
root = xmlDocGetRootElement(instance);
|
||||
if (root == NULL) {
|
||||
TODO
|
||||
/* TODO */
|
||||
ctxt->nberrors++;
|
||||
return(1);
|
||||
}
|
||||
@ -1958,7 +1975,8 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
|
||||
if (xmlPatternMatch(rule->pattern, cur) == 1) {
|
||||
test = rule->tests;
|
||||
|
||||
if (xmlSchematronRegisterVariables(ctxt->xctxt, rule->lets, instance, cur))
|
||||
if (xmlSchematronRegisterVariables(ctxt, ctxt->xctxt,
|
||||
rule->lets, instance, cur))
|
||||
return -1;
|
||||
|
||||
while (test != NULL) {
|
||||
@ -1966,7 +1984,8 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
|
||||
test = test->next;
|
||||
}
|
||||
|
||||
if (xmlSchematronUnregisterVariables(ctxt->xctxt, rule->lets))
|
||||
if (xmlSchematronUnregisterVariables(ctxt, ctxt->xctxt,
|
||||
rule->lets))
|
||||
return -1;
|
||||
|
||||
}
|
||||
@ -1996,15 +2015,16 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance)
|
||||
while (rule != NULL) {
|
||||
if (xmlPatternMatch(rule->pattern, cur) == 1) {
|
||||
test = rule->tests;
|
||||
xmlSchematronRegisterVariables(ctxt->xctxt, rule->lets,
|
||||
instance, cur);
|
||||
xmlSchematronRegisterVariables(ctxt, ctxt->xctxt,
|
||||
rule->lets, instance, cur);
|
||||
|
||||
while (test != NULL) {
|
||||
xmlSchematronRunTest(ctxt, test, instance, cur, pattern);
|
||||
test = test->next;
|
||||
}
|
||||
|
||||
xmlSchematronUnregisterVariables(ctxt->xctxt, rule->lets);
|
||||
xmlSchematronUnregisterVariables(ctxt, ctxt->xctxt,
|
||||
rule->lets);
|
||||
}
|
||||
rule = rule->patnext;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user