2

libxml2 を使用して、xsd スキーマに対して xml ファイルを検証しています。xmlSchemaSetParserErrors 関数を使用すると、stderr にエラーが出力されます。これらの検証エラーを取得してメモリに保存し、ユーザーに表示する必要があります。これらのエラーをリダイレクトするにはどうすればよいですか? いくつかの例を教えてください。ありがとう、アンドレア

4

3 に答える 3

2

またはさらに簡潔に:

void err(void *ctx, const char *msg, ...)
{
    va_list args;
    va_start(args, msg);
    char *val = va_arg(args,char*);
    va_end(args);
}

val に検証エラーが含まれるようになりました

于 2012-08-30T08:43:45.483 に答える
2

この例では、パーサー モジュールの検証コールバック メカニズムを使用します。が期待するコールバックのシグネチャはxmlSchemaSetParserErrors同じようです。

#include <iostream>
#include <cstdarg>
#include <cstdio>
#include <vector>
#include <string>
#include <iterator>
#include <libxml/parser.h>
#include <libxml/tree.h>

struct ParserContext
{
    ParserContext() : context(xmlNewParserCtxt()) {}
    ~ParserContext() { xmlFreeParserCtxt(context); }
    xmlParserCtxtPtr context;
private:
    ParserContext(ParserContext&);
    void operator=(ParserContext&);
};



struct ErrorHandler
{
    std::vector<std::string> errors;

    void RegisterErrorHandling(xmlValidCtxt& validationContext)
    {
        // Change this to register for schema errors...
        validationContext.userData = this;
        validationContext.error = &ErrorHandler::Handle;
    }

private:
    static void Handle(void *handler, const char *format, ...)
    {
        va_list arguments;
        va_start(arguments, format);
        std::string message = MakeMessage(format, arguments);
        va_end(arguments);

        ErrorHandler* errorHandler = static_cast<ErrorHandler*>(handler);
        errorHandler->errors.push_back(message);
    }

    static std::string MakeMessage(const char* format, va_list arguments)
    {
        const size_t bufferSize = 200;
        std::vector<char> buffer(bufferSize, 0);

        size_t charactersWritten = 
            vsnprintf(&buffer.front(), bufferSize, format, arguments);
        if (charactersWritten == -1)
            buffer.back() = 0;  // Message truncated!
        return std::string(&buffer.front());
    }
};


struct XmlDocument
{
    static XmlDocument FromFile(const char* fileName)
    {
        ParserContext parser;
        ErrorHandler errorHandler;
        errorHandler.RegisterErrorHandling(parser.context->vctxt);
        XmlDocument document(xmlCtxtReadFile(
            parser.context, fileName, NULL, XML_PARSE_DTDVALID));
        document.errors = move(errorHandler.errors);
        return document;
    }

    XmlDocument(XmlDocument&& other) : 
        xmlPointer(other.xmlPointer),
        errors(move(other.errors))
    {
        other.xmlPointer = nullptr;
    }

    ~XmlDocument() 
    { 
        xmlFreeDoc(xmlPointer); 
    }

    xmlDocPtr xmlPointer;
    std::vector<std::string> errors;

private:
    XmlDocument(xmlDocPtr pointer) : xmlPointer(pointer) {}
    XmlDocument(XmlDocument&);
    void operator=(XmlDocument&);
};


void DisplayErrorsToUser(
    const XmlDocument& document, 
    std::ostream& displayStream = std::cout)
{
    using namespace std;
    copy(begin(document.errors), end(document.errors),
        ostream_iterator<string>(displayStream, "\n"));
}

int main()
{
    auto xml = XmlDocument::FromFile("test.xml");
    DisplayErrorsToUser(xml);
}
于 2012-08-24T11:41:29.580 に答える
1

API ドキュメントで述べたように、xmlSchemaSetParserErrors() Set the callback functions used to handle errors for a validation context.

定義された署名に関して、2 つのコールバック関数を記述する必要があります。

例は次のとおりです。

void err(void *ctx, const char *msg, ...)
{
  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);

  if(len==0) // Can't create schema validity error!
  else       // Do something to store `buf`, 
             // you may need to use void *ctx to achieve this

  return;
}

あとは電話するだけ

xmlSchemaSetValidErrors(valid_ctxt_ptr, (xmlSchemaValidityErrorFunc) err, (xmlSchemaValidityWarningFunc) warn, ctx);

電話する前に

xmlSchemaValidateDoc()
于 2012-08-28T13:37:34.740 に答える