Как прекратить анализ XML-документа с LIBXML SAX в любое время?

У меня есть 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) но в функции обратного вызова ошибки схемы отсутствует контекст синтаксического анализатора.

Пожалуйста помоги! Спасибо!

1 ответ

Я знаю, что вы опубликовали это давным-давно, так что вам может быть все равно, но у меня была похожая проблема. В случае, если кто-то столкнется с этим, я думаю, что ответ использует контекст 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);
Другие вопросы по тегам