2012-08-24 48 views
2

我正在使用libxml2根據xsd模式驗證xml文件。 使用xmlSchemaSetParserErrors函數,將錯誤輸出到stderr。 我需要得到這些驗證錯誤,將它們存儲在內存中並顯示給用戶。 我該如何重定向這些錯誤?你能提供一些例子嗎? 謝謝, Andrealibxml2獲取驗證錯誤

+0

除非我遺漏了一些東西,* xmlSchemaSetParserErrors()*可用於設置您自己的回調錯誤。那麼,問題在哪裏,先生? –

+0

沒有問題,我只是在尋找一個關於如何爲錯誤設置自定義回調的例子。 –

回答

2

本示例使用解析器模塊的驗證回調機制。​​預計回調的簽名似乎是相同的。

#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); 
} 
1

正如API文檔中說,xmlSchemaSetParserErrors()Set the callback functions used to handle errors for a validation context.

你需要寫關於兩個回調函數來定義的特徵:

一個例子可以是:

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() 
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現在包含驗證錯誤