Итак, ваши вопросы заставили меня задуматься, и когда я заглянул в документацию libxml2 ,
Structure xmlError
struct _xmlError {
int domain : What part of the library raised this er
int code : The error code, e.g. an xmlParserError
char * message : human-readable informative error messag
xmlErrorLevel level : how consequent is the error
char * file : the filename
int line : the line number if available
char * str1 : extra string information
char * str2 : extra string information
char * str3 : extra string information
int int1 : extra number information
int int2 : error column # or 0 if N/A (todo: renam
void * ctxt : the parser context if available
void * node : the node in the tree
}
, где мы можем ясно видеть, что xmlErrorPtr
, который возвращается функцией xmlGetLastError()
, четко содержит информацию о имени файла, номере строки и номере столбца.
char * file : the filename
int line : the line number if available
...
int int2 : error column
Итак, чтобы проверить, было ли это возможно или нет, вот код, который я использовал (в основном ваш код с небольшими изменениями, чтобы он работал в моей системе):
#include <stdio.h>
#include <stdbool.h>
#include <libxml/xmlreader.h>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>
static void schemaParseErrorHandler(void *arg, xmlErrorPtr error)
{
fprintf(stderr, "Error at line %d, column %d\n%s", error->line, error->int2, error->message);
*((bool*)arg) = true;
}
int main( int argc, char **argv )
{
xmlInitParser();
xmlSchemaPtr schema = NULL;
xmlSchemaParserCtxtPtr schema_parser_ctxt = NULL;
int has_schema_errors = 0;
int ret = -1;
xmlSchemaValidCtxtPtr valid_ctxt = NULL;
if ((schema_parser_ctxt = xmlSchemaNewParserCtxt("/home/junglefox/shiporder.xsd")))
{
schema = xmlSchemaParse(schema_parser_ctxt);
xmlSchemaFreeParserCtxt(schema_parser_ctxt);
if (schema)
{
valid_ctxt = xmlSchemaNewValidCtxt(schema);
}
}
xmlTextReaderPtr reader = NULL;
const char* filename = "/home/junglefox/shiporder.xml";
reader = xmlReaderForFile(filename, /*RPCXmlStream::STD_ENCODING,*/ NULL, 0);
if (reader != NULL)
{
if (valid_ctxt)
{
xmlTextReaderSchemaValidateCtxt(reader, valid_ctxt, 0);
xmlSchemaSetValidStructuredErrors(valid_ctxt, schemaParseErrorHandler, &has_schema_errors);
}
ret = xmlTextReaderRead(reader);
while (ret == 1 && !has_schema_errors)
{
//... procesing informations
ret = xmlTextReaderRead(reader);
}
}
if (ret != 0)
{
xmlErrorPtr err = xmlGetLastError();
fprintf(stdout, "%s: failed to parse in line %d, col %d. Error %d: %s\n",
err->file,
err->line,
err->int2,
err->code,
err->message);
}
xmlFreeTextReader(reader);
xmlCleanupParser();
return 0;
}
где shiporder.xml и shiporder.xsd , использованные в этой программе, были скопированы из url и сохранены локально.
Я скомпилировал и запустил код следующим образом:
junglefox@ubuntu:~$ gcc -o test_xsd main.c -I/usr/include/libxml2/ -lxml2 -L/usr/lib/x86_64-linux-gnu/
junglefox@ubuntu:~$ ./test_xsd
junglefox@ubuntu:~$
На этот раз на выходе ничего не было. Как и должно быть, так как ошибок не было.
Если, однако, теперь я делаю преднамеренную ошибку в файле shiporder.xml , как показано ниже:
Вот частичный -сниппет из багги shiporder.xml :
<?xml version="1.0" encoding="UTF-8"?>
...
<item>
<title>Hide your heart</title>
<quantity>1</quantity>
price>9.90</price>
</item>
</shiporder>
Обратите внимание на пропавших без вести <
до price
!
Теперь я снова запускаю программу,
junglefox@ubuntu:~$ ./test_xsd
Error at line 22, column 0
Element 'item': Character content other than whitespace is not allowed because the content type is 'element-only'.
который отвечает на ваш вопрос (ы):
При моем подходе я получаю ошибки проверки в функции schemaParseErrorHandler, но без номеров строк или столбцов. Как я могу получить эту информацию?
и
Итак, как правильно сделать проверку, чтобы информация об ошибках включала номера строк и столбцов?
, поскольку в выводе четко отображаются строки с номером 22 * 1066 * и столбец 0 , где произошел неожиданный empty space
из-за отсутствия <
.