mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-23 01:52:48 +03:00
Fix file and line report for XSD SAX and reader streaming validation
Things now work correctly at the xmllint level: thinkpad:~/XML -> xmllint --sax --noout --schema test_schema.xsd test_xml.xml test_xml.xml:72721: Schemas validity error : Element 'level1': Missing child element(s). Expected is ( level2 ). test_xml.xml fails to validate thinkpad:~/XML -> xmllint --stream --schema test_schema.xsd test_xml.xml test_xml.xml:72721: Schemas validity error : Element 'level1': Missing child element(s). Expected is ( level2 ). test_xml.xml fails to validate thinkpad:~/XML -> * error.c: fix a corner case of not reporting lines when we should * include/libxml/xmlschemas.h doc/symbols.xml: had to add new entry points to set the filename on a validation context and a locator callback used to fetch the line and file from the context * xmlschemas.c: add the new entry points xmlSchemaValidateSetFilename() and xmlSchemaValidateSetLocator(), plus make sure the error reporting routine gets the information if available. Add a locator for SAX. * xmlreader.c: add and plug a locator for readers.
This commit is contained in:
@@ -1754,6 +1754,8 @@
|
|||||||
<symbol file="tree">xmlBufUse</symbol>
|
<symbol file="tree">xmlBufUse</symbol>
|
||||||
<symbol file="dict">xmlDictGetUsage</symbol>
|
<symbol file="dict">xmlDictGetUsage</symbol>
|
||||||
<symbol file="dict">xmlDictSetLimit</symbol>
|
<symbol file="dict">xmlDictSetLimit</symbol>
|
||||||
|
<symbol file="xmlschemas">xmlSchemaValidateSetFilename</symbol>
|
||||||
|
<symbol file="xmlschemas">xmlSchemaValidateSetLocator</symbol>
|
||||||
<symbol file="xmlIO">xmlOutputBufferGetContent</symbol>
|
<symbol file="xmlIO">xmlOutputBufferGetContent</symbol>
|
||||||
<symbol file="xmlIO">xmlOutputBufferGetSize</symbol>
|
<symbol file="xmlIO">xmlOutputBufferGetSize</symbol>
|
||||||
</release>
|
</release>
|
||||||
|
5
error.c
5
error.c
@@ -292,7 +292,10 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
|
|||||||
} else {
|
} else {
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
channel(data, "%s:%d: ", file, line);
|
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);
|
channel(data, "Entity: line %d: ", line);
|
||||||
}
|
}
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
|
@@ -113,6 +113,22 @@ typedef xmlSchemaParserCtxt *xmlSchemaParserCtxtPtr;
|
|||||||
typedef struct _xmlSchemaValidCtxt xmlSchemaValidCtxt;
|
typedef struct _xmlSchemaValidCtxt xmlSchemaValidCtxt;
|
||||||
typedef xmlSchemaValidCtxt *xmlSchemaValidCtxtPtr;
|
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.
|
* Interfaces for parsing.
|
||||||
*/
|
*/
|
||||||
@@ -171,6 +187,9 @@ XMLPUBFUN int XMLCALL
|
|||||||
XMLPUBFUN int XMLCALL
|
XMLPUBFUN int XMLCALL
|
||||||
xmlSchemaSetValidOptions (xmlSchemaValidCtxtPtr ctxt,
|
xmlSchemaSetValidOptions (xmlSchemaValidCtxtPtr ctxt,
|
||||||
int options);
|
int options);
|
||||||
|
XMLPUBFUN void XMLCALL
|
||||||
|
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,
|
||||||
|
const char *filename);
|
||||||
XMLPUBFUN int XMLCALL
|
XMLPUBFUN int XMLCALL
|
||||||
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt);
|
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt);
|
||||||
|
|
||||||
@@ -210,6 +229,13 @@ XMLPUBFUN xmlSchemaSAXPlugPtr XMLCALL
|
|||||||
void **user_data);
|
void **user_data);
|
||||||
XMLPUBFUN int XMLCALL
|
XMLPUBFUN int XMLCALL
|
||||||
xmlSchemaSAXUnplug (xmlSchemaSAXPlugPtr plug);
|
xmlSchemaSAXUnplug (xmlSchemaSAXPlugPtr plug);
|
||||||
|
|
||||||
|
|
||||||
|
XMLPUBFUN void XMLCALL
|
||||||
|
xmlSchemaValidateSetLocator (xmlSchemaValidCtxtPtr vctxt,
|
||||||
|
xmlSchemaValidityLocatorFunc f,
|
||||||
|
void *ctxt);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1669,6 +1669,7 @@ testSAX(const char *filename) {
|
|||||||
(xmlSchemaValidityErrorFunc) fprintf,
|
(xmlSchemaValidityErrorFunc) fprintf,
|
||||||
(xmlSchemaValidityWarningFunc) fprintf,
|
(xmlSchemaValidityWarningFunc) fprintf,
|
||||||
stderr);
|
stderr);
|
||||||
|
xmlSchemaValidateSetFilename(vctxt, filename);
|
||||||
|
|
||||||
ret = xmlSchemaValidateStream(vctxt, buf, 0, handler,
|
ret = xmlSchemaValidateStream(vctxt, buf, 0, handler,
|
||||||
(void *)user_data);
|
(void *)user_data);
|
||||||
|
61
xmlreader.c
61
xmlreader.c
@@ -4154,6 +4154,60 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
|
|||||||
return(0);
|
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:
|
* xmlTextReaderSetSchema:
|
||||||
* @reader: the xmlTextReaderPtr used
|
* @reader: the xmlTextReaderPtr used
|
||||||
@@ -4221,6 +4275,10 @@ xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
|
|||||||
reader->xsdValidCtxt = NULL;
|
reader->xsdValidCtxt = NULL;
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
|
||||||
|
xmlTextReaderLocator,
|
||||||
|
(void *) reader);
|
||||||
|
|
||||||
if (reader->errorFunc != NULL) {
|
if (reader->errorFunc != NULL) {
|
||||||
xmlSchemaSetValidErrors(reader->xsdValidCtxt,
|
xmlSchemaSetValidErrors(reader->xsdValidCtxt,
|
||||||
xmlTextReaderValidityErrorRelay,
|
xmlTextReaderValidityErrorRelay,
|
||||||
@@ -4435,6 +4493,9 @@ xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
|
|||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
|
||||||
|
xmlTextReaderLocator,
|
||||||
|
(void *) reader);
|
||||||
/*
|
/*
|
||||||
* Redirect the validation context's error channels to use
|
* Redirect the validation context's error channels to use
|
||||||
* the reader channels.
|
* the reader channels.
|
||||||
|
106
xmlschemas.c
106
xmlschemas.c
@@ -975,6 +975,7 @@ struct _xmlSchemaValidCtxt {
|
|||||||
xmlSAXHandlerPtr sax;
|
xmlSAXHandlerPtr sax;
|
||||||
xmlParserCtxtPtr parserCtxt;
|
xmlParserCtxtPtr parserCtxt;
|
||||||
void *user_data; /* TODO: What is this for? */
|
void *user_data; /* TODO: What is this for? */
|
||||||
|
char *filename;
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
int nberrors;
|
int nberrors;
|
||||||
@@ -1028,6 +1029,10 @@ struct _xmlSchemaValidCtxt {
|
|||||||
int hasKeyrefs;
|
int hasKeyrefs;
|
||||||
int createIDCNodeTables;
|
int createIDCNodeTables;
|
||||||
int psviExposeIDCNodeTables;
|
int psviExposeIDCNodeTables;
|
||||||
|
|
||||||
|
/* Locator for error reporting in streaming mode */
|
||||||
|
xmlSchemaValidityLocatorFunc locFunc;
|
||||||
|
void *locCtxt;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2078,6 +2083,20 @@ xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
|
|||||||
(vctxt->parserCtxt->input != NULL))
|
(vctxt->parserCtxt->input != NULL))
|
||||||
file = vctxt->parserCtxt->input->filename;
|
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,
|
__xmlRaiseError(schannel, channel, data, ctxt,
|
||||||
node, XML_FROM_SCHEMASV,
|
node, XML_FROM_SCHEMASV,
|
||||||
error, errorLevel, file, line,
|
error, errorLevel, file, line,
|
||||||
@@ -27450,8 +27469,28 @@ xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlSchemaClearValidCtxt:
|
* xmlSchemaValidateSetFilename:
|
||||||
* @ctxt: the schema validation context
|
* @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;
|
* Free the resources associated to the schema validation context;
|
||||||
* leaves some fields alive intended for reuse of the context.
|
* leaves some fields alive intended for reuse of the context.
|
||||||
@@ -27552,6 +27591,11 @@ xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
|
|||||||
* where the user provides the dict?
|
* where the user provides the dict?
|
||||||
*/
|
*/
|
||||||
vctxt->dict = xmlDictCreate();
|
vctxt->dict = xmlDictCreate();
|
||||||
|
|
||||||
|
if (vctxt->filename != NULL) {
|
||||||
|
xmlFree(vctxt->filename);
|
||||||
|
vctxt->filename = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27637,6 +27681,8 @@ xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
|
|||||||
xmlSchemaItemListFree(ctxt->nodeQNames);
|
xmlSchemaItemListFree(ctxt->nodeQNames);
|
||||||
if (ctxt->dict != NULL)
|
if (ctxt->dict != NULL)
|
||||||
xmlDictFree(ctxt->dict);
|
xmlDictFree(ctxt->dict);
|
||||||
|
if (ctxt->filename != NULL)
|
||||||
|
xmlFree(ctxt->filename);
|
||||||
xmlFree(ctxt);
|
xmlFree(ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28630,6 +28676,63 @@ xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
|
|||||||
return(0);
|
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:
|
* xmlSchemaValidateStream:
|
||||||
* @ctxt: a schema validation context
|
* @ctxt: a schema validation context
|
||||||
@@ -28673,6 +28776,7 @@ xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
|
|||||||
xmlCtxtUseOptions(pctxt, options);
|
xmlCtxtUseOptions(pctxt, options);
|
||||||
#endif
|
#endif
|
||||||
pctxt->linenumbers = 1;
|
pctxt->linenumbers = 1;
|
||||||
|
xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
|
||||||
|
|
||||||
inputStream = xmlNewIOInputStream(pctxt, input, enc);;
|
inputStream = xmlNewIOInputStream(pctxt, input, enc);;
|
||||||
if (inputStream == NULL) {
|
if (inputStream == NULL) {
|
||||||
|
Reference in New Issue
Block a user