1
0
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:
Daniel Veillard
2012-08-14 11:01:07 +08:00
parent aabc08477c
commit 97fa5b3c8f
6 changed files with 199 additions and 2 deletions

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);

View File

@@ -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.

View File

@@ -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) {