У меня есть Win32 C ++ код, который использует парсер LIBXML SAX. Этот код анализирует большой XML-файл (> 1 ГБ) и проверяет его с помощью схемы xsd. Когда возникает ошибка проверки xsd, LIBXML вызывает обратный вызов и продолжает анализ. Я хочу остановить процесс синтаксического анализа в этом обратном вызове. До сих пор я достигаю этого результата, поднимая исключение c ++. Но такой подход оставляет неизданные ресурсы и вызывает утечки памяти.
SAX Запуск кода:
xmlSchemaParserCtxtPtr sch = xmlSchemaNewParserCtxt("MUXGate.xsd");
xmlSchemaPtr schema = xmlSchemaParse(sch);
xmlSchemaValidCtxtPtr vsch = xmlSchemaNewValidCtxt(schema);
context.vsch = xmlSchemaNewValidCtxt(schema);
xmlSchemaSetValidErrors(
vsch,
xmlMySchemaValidityErrorFunc,
xmlMySchemaValidityWarningFunc,
&context);
xmlSAXHandlerPtr hndlrptr = &my_handler;
void* ctxptr = &context;
xmlSchemaSAXPlugPtr saxPlug = xmlSchemaSAXPlug(vsch,&hndlrptr,&ctxptr);try{
if (xmlSAXUserParseFile(hndlrptr, ctxptr , "errschema.xml1") < 0) {
xmess<<"Parse error\n";
} else
xmess<<"Parse ok\n";
if(context.SchemaError)
{
xmess <<"Schema error\n";
}
}
catch(...) //Catching exception
{
xmess<<"Exception\n";
}
xmlSchemaSAXUnplug(saxPlug);
xmlSchemaFreeValidCtxt(context.vsch);
xmlSchemaFreeValidCtxt(vsch);
xmlSchemaFree(schema);
xmlSchemaFreeParserCtxt(sch);
Обратный вызов ошибки схемы:
void xmlMySchemaValidityErrorFunc (void * ctx,
const char * msg,
...)
{
MyContext& context = *(MyContext*)ctx;
context.SchemaError = true;
char buf[1024];
va_list args;
va_start(args, msg);
int len = vsnprintf_s(buf, sizeof(buf), sizeof(buf)/sizeof(buf[0]), msg, args);
va_end(args);
puts(buf);
throw new int(1); //throwing an exception
}
Есть функция void xmlStopParser (xmlParserCtxtPtr ctxt)
но в функции обратного вызова ошибки схемы отсутствует контекст синтаксического анализатора.
Пожалуйста помоги!
Спасибо!
Я знаю, что вы опубликовали это давным-давно, так что вам может быть все равно, но у меня была похожая проблема. В случае, если кто-то столкнется с этим, я думаю, что ответ использует контекст push. Здесь вы постоянно помещаете новые данные в парсер. Когда вы сталкиваетесь с ошибкой, вы можете перестать выдвигать данные и звонить бесплатно. Вот пример кода из libSml2 testSAX.c:
if (sax2)
ctxt = xmlCreatePushParserCtxt(debugSAX2Handler, NULL,
chars, ret, filename);
else
ctxt = xmlCreatePushParserCtxt(debugSAXHandler, NULL,
chars, ret, filename);
while ((ret = fread(chars, 1, 3, f)) > 0) {
xmlParseChunk(ctxt, chars, ret, 0);
}
ret = xmlParseChunk(ctxt, chars, 0, 1);
xmlFreeParserCtxt(ctxt);