diff --git a/doc/symbols.xml b/doc/symbols.xml index ee16185e..7f6d692b 100644 --- a/doc/symbols.xml +++ b/doc/symbols.xml @@ -1754,6 +1754,8 @@ xmlBufUse xmlDictGetUsage xmlDictSetLimit + xmlSchemaValidateSetFilename + xmlSchemaValidateSetLocator xmlOutputBufferGetContent xmlOutputBufferGetSize diff --git a/error.c b/error.c index b5e4c283..1c2fb36e 100644 --- a/error.c +++ b/error.c @@ -292,7 +292,10 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str, } else { if (file != NULL) channel(data, "%s:%d: ", file, line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) + else if ((line != 0) && + ((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)|| + (domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) || + (domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV))) channel(data, "Entity: line %d: ", line); } if (name != NULL) { diff --git a/include/libxml/xmlschemas.h b/include/libxml/xmlschemas.h index 752bc3ad..b070d5c5 100644 --- a/include/libxml/xmlschemas.h +++ b/include/libxml/xmlschemas.h @@ -113,6 +113,22 @@ typedef xmlSchemaParserCtxt *xmlSchemaParserCtxtPtr; typedef struct _xmlSchemaValidCtxt xmlSchemaValidCtxt; typedef xmlSchemaValidCtxt *xmlSchemaValidCtxtPtr; +/** + * xmlSchemaValidityLocatorFunc: + * @ctx: user provided context + * @file: returned file information + * @line: returned line information + * + * A schemas validation locator, a callback called by the validator. + * This is used when file or node informations are not available + * to find out what file and line number are affected + * + * Returns: 0 in case of success and -1 in case of error + */ + +typedef int (XMLCDECL *xmlSchemaValidityLocatorFunc) (void *ctx, + const char **file, unsigned long *line); + /* * Interfaces for parsing. */ @@ -171,6 +187,9 @@ XMLPUBFUN int XMLCALL XMLPUBFUN int XMLCALL xmlSchemaSetValidOptions (xmlSchemaValidCtxtPtr ctxt, int options); +XMLPUBFUN void XMLCALL + xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, + const char *filename); XMLPUBFUN int XMLCALL xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt); @@ -210,6 +229,13 @@ XMLPUBFUN xmlSchemaSAXPlugPtr XMLCALL void **user_data); XMLPUBFUN int XMLCALL xmlSchemaSAXUnplug (xmlSchemaSAXPlugPtr plug); + + +XMLPUBFUN void XMLCALL + xmlSchemaValidateSetLocator (xmlSchemaValidCtxtPtr vctxt, + xmlSchemaValidityLocatorFunc f, + void *ctxt); + #ifdef __cplusplus } #endif diff --git a/xmllint.c b/xmllint.c index 78db222c..b58d1843 100644 --- a/xmllint.c +++ b/xmllint.c @@ -1669,6 +1669,7 @@ testSAX(const char *filename) { (xmlSchemaValidityErrorFunc) fprintf, (xmlSchemaValidityWarningFunc) fprintf, stderr); + xmlSchemaValidateSetFilename(vctxt, filename); ret = xmlSchemaValidateStream(vctxt, buf, 0, handler, (void *)user_data); diff --git a/xmlreader.c b/xmlreader.c index f9c7fa17..c6ca46eb 100644 --- a/xmlreader.c +++ b/xmlreader.c @@ -4154,6 +4154,60 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) { return(0); } +/** + * xmlTextReaderLocator: + * @ctx: the xmlTextReaderPtr used + * @file: returned file information + * @line: returned line information + * + * Internal locator function for the readers + * + * Returns 0 in case the Schema validation could be (des)activated and + * -1 in case of error. + */ +static int +xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) { + xmlTextReaderPtr reader; + + if ((ctx == NULL) || ((file == NULL) && (line == NULL))) + return(-1); + + if (file != NULL) + *file = NULL; + if (line != NULL) + *line = 0; + + reader = (xmlTextReaderPtr) ctx; + if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) { + if (file != NULL) + *file = reader->ctxt->input->filename; + if (line != NULL) + *line = reader->ctxt->input->line; + return(0); + } + if (reader->node != NULL) { + long res; + int ret = 0; + + if (line != NULL) { + res = xmlGetLineNo(reader->node); + if (res > 0) + *line = (unsigned long) res; + else + ret = -1; + } + if (file != NULL) { + xmlDocPtr doc = reader->node->doc; + if ((doc != NULL) && (doc->URL != NULL)) + *file = (const char *) doc->URL; + else + ret = -1; + } + return(ret); + } + return(-1); +} + /** * xmlTextReaderSetSchema: * @reader: the xmlTextReaderPtr used @@ -4221,6 +4275,10 @@ xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) { reader->xsdValidCtxt = NULL; return(-1); } + xmlSchemaValidateSetLocator(reader->xsdValidCtxt, + xmlTextReaderLocator, + (void *) reader); + if (reader->errorFunc != NULL) { xmlSchemaSetValidErrors(reader->xsdValidCtxt, xmlTextReaderValidityErrorRelay, @@ -4435,6 +4493,9 @@ xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader, return(-1); } } + xmlSchemaValidateSetLocator(reader->xsdValidCtxt, + xmlTextReaderLocator, + (void *) reader); /* * Redirect the validation context's error channels to use * the reader channels. diff --git a/xmlschemas.c b/xmlschemas.c index 2fb21511..de079933 100644 --- a/xmlschemas.c +++ b/xmlschemas.c @@ -975,6 +975,7 @@ struct _xmlSchemaValidCtxt { xmlSAXHandlerPtr sax; xmlParserCtxtPtr parserCtxt; void *user_data; /* TODO: What is this for? */ + char *filename; int err; int nberrors; @@ -1028,6 +1029,10 @@ struct _xmlSchemaValidCtxt { int hasKeyrefs; int createIDCNodeTables; int psviExposeIDCNodeTables; + + /* Locator for error reporting in streaming mode */ + xmlSchemaValidityLocatorFunc locFunc; + void *locCtxt; }; /** @@ -2078,6 +2083,20 @@ xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt, (vctxt->parserCtxt->input != NULL)) file = vctxt->parserCtxt->input->filename; } + if (vctxt->locFunc != NULL) { + if ((file == NULL) || (line == 0)) { + unsigned long l; + const char *f; + vctxt->locFunc(vctxt->locCtxt, &f, &l); + if (file == NULL) + file = f; + if (line == 0) + line = (int) l; + } + } + if ((file == NULL) && (vctxt->filename != NULL)) + file = vctxt->filename; + __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV, error, errorLevel, file, line, @@ -27450,8 +27469,28 @@ xmlSchemaNewValidCtxt(xmlSchemaPtr schema) } /** - * xmlSchemaClearValidCtxt: + * xmlSchemaValidateSetFilename: * @ctxt: the schema validation context + * @filename: the file name + * + * Workaround to provide file error reporting information when this is + * not provided by current APIs + */ +void +xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) { + if (vctxt == NULL) + return; + if (vctxt->filename != NULL) + xmlFree(vctxt->filename); + if (filename != NULL) + vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename); + else + vctxt->filename = NULL; +} + +/** + * xmlSchemaClearValidCtxt: + * @vctxt: the schema validation context * * Free the resources associated to the schema validation context; * leaves some fields alive intended for reuse of the context. @@ -27552,6 +27591,11 @@ xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt) * where the user provides the dict? */ vctxt->dict = xmlDictCreate(); + + if (vctxt->filename != NULL) { + xmlFree(vctxt->filename); + vctxt->filename = NULL; + } } /** @@ -27637,6 +27681,8 @@ xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) xmlSchemaItemListFree(ctxt->nodeQNames); if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); + if (ctxt->filename != NULL) + xmlFree(ctxt->filename); xmlFree(ctxt); } @@ -28630,6 +28676,63 @@ xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug) return(0); } +/** + * xmlSchemaValidateSetLocator: + * @vctxt: a schema validation context + * @f: the locator function pointer + * @ctxt: the locator context + * + * Allows to set a locator function to the validation context, + * which will be used to provide file and line information since + * those are not provided as part of the SAX validation flow + * Setting @f to NULL disable the locator. + */ + +void +xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaValidityLocatorFunc f, + void *ctxt) +{ + if (vctxt == NULL) return; + vctxt->locFunc = f; + vctxt->locCtxt = ctxt; +} + +/** + * xmlSchemaValidateStreamLocator: + * @ctx: the xmlTextReaderPtr used + * @file: returned file information + * @line: returned line information + * + * Internal locator function for the readers + * + * Returns 0 in case the Schema validation could be (des)activated and + * -1 in case of error. + */ +static int +xmlSchemaValidateStreamLocator(void *ctx, const char **file, + unsigned long *line) { + xmlParserCtxtPtr ctxt; + + if ((ctx == NULL) || ((file == NULL) && (line == NULL))) + return(-1); + + if (file != NULL) + *file = NULL; + if (line != NULL) + *line = 0; + + ctxt = (xmlParserCtxtPtr) ctx; + if (ctxt->input != NULL) { + if (file != NULL) + *file = ctxt->input->filename; + if (line != NULL) + *line = ctxt->input->line; + return(0); + } + return(-1); +} + /** * xmlSchemaValidateStream: * @ctxt: a schema validation context @@ -28673,6 +28776,7 @@ xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt, xmlCtxtUseOptions(pctxt, options); #endif pctxt->linenumbers = 1; + xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt); inputStream = xmlNewIOInputStream(pctxt, input, enc);; if (inputStream == NULL) {