[libxml2] Fix file and line report for XSD SAX and reader streaming validation



commit 97fa5b3c8f3fe6ff79123ab43ed6b846fd1dd6dd
Author: Daniel Veillard <veillard redhat com>
Date:   Tue Aug 14 11:01:07 2012 +0800

    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.

 doc/symbols.xml             |    2 +
 error.c                     |    5 ++-
 include/libxml/xmlschemas.h |   26 +++++++++++
 xmllint.c                   |    1 +
 xmlreader.c                 |   61 +++++++++++++++++++++++++
 xmlschemas.c                |  106 ++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 199 insertions(+), 2 deletions(-)
---
diff --git a/doc/symbols.xml b/doc/symbols.xml
index ee16185..7f6d692 100644
--- a/doc/symbols.xml
+++ b/doc/symbols.xml
@@ -1754,6 +1754,8 @@
     <symbol file="tree">xmlBufUse</symbol>
     <symbol file="dict">xmlDictGetUsage</symbol>
     <symbol file="dict">xmlDictSetLimit</symbol>
+    <symbol file="xmlschemas">xmlSchemaValidateSetFilename</symbol>
+    <symbol file="xmlschemas">xmlSchemaValidateSetLocator</symbol>
     <symbol file="xmlIO">xmlOutputBufferGetContent</symbol>
     <symbol file="xmlIO">xmlOutputBufferGetSize</symbol>
   </release>
diff --git a/error.c b/error.c
index b5e4c28..1c2fb36 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 752bc3a..b070d5c 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 78db222..b58d184 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 f9c7fa1..c6ca46e 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -4155,6 +4155,60 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
 }
 
 /**
+ * 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
  * @schema:  a precompiled Schema schema
@@ -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 2fb2151..de07993 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);
 }
 
@@ -28631,6 +28677,63 @@ xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
 }
 
 /**
+ * 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
  * @input:  the input to use for reading the data
@@ -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) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]