【问题标题】:xml file validation with in-memory schema in xerces c++在xerces c ++中使用内存模式验证xml文件
【发布时间】:2014-03-21 17:10:18
【问题描述】:
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/dom/DOMLSParser.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/sax/ErrorHandler.hpp>
#include <xercesc/sax/SAXParseException.hpp>
#include <xercesc/sax/Parser.hpp>
#include <xercesc/validators/common/Grammar.hpp>

class CErrorHandler : public xercesc::DefaultHandler 
{
public:    
CErrorHandler();

virtual ~CErrorHandler();

void startElement(const   XMLCh* const    uri,
                  const   XMLCh* const    localname,
                  const   XMLCh* const    qname,
                  const   XERCES_CPP_NAMESPACE::Attributes&     attrs
);

void endElement(const   XMLCh* const    uri,
                const   XMLCh* const    localname,
                const   XMLCh* const    qname
);

void characters(const   XMLCh* const    chars,
                const   XMLSize_t       length
);

void fatalError(const xercesc::SAXParseException&);
};

   CErrorHandler::CErrorHandler()
   {
   }

   CErrorHandler::~CErrorHandler()
   {
   }

   void CErrorHandler::startElement(const   XMLCh* const    uri,
                                    const   XMLCh* const    localname,
                                    const   XMLCh* const    qname,
                                    const   xercesc::Attributes&     attrs)
   {
      char* name = xercesc::XMLString::transcode(localname);
      std::cout << name;
      xercesc::XMLString::release(&name);
   }

   void CErrorHandler::endElement(const   XMLCh* const    uri,
                                  const   XMLCh* const    localname,
                                  const   XMLCh* const    qname)
   {
      char* name = xercesc::XMLString::transcode(localname);
      xercesc::XMLString::release(&name);
   }

   void CErrorHandler::fatalError(const xercesc::SAXParseException& exception)
   {
      char* message = xercesc::XMLString::transcode(exception.getMessage());
      std::cout << "Error: " << message << " at line: " << exception.getLineNumber() << std::endl;
      xercesc::XMLString::release(&message);
   }

   void CErrorHandler::characters(const   XMLCh* const    chars,
                                  const   XMLSize_t       length
   )
   {
   }

bool validateSchema()
{

std::string XSD_SHEMA ="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>...";   

try 
   {
      xercesc::XMLPlatformUtils::Initialize();
   }

   catch (const  XERCES_CPP_NAMESPACE::XMLException& toCatch) 
   {
      char* message =  xercesc::XMLString::transcode(toCatch.getMessage());
      std::cout << "Error during initialization!" << std::endl;
      std::cout << "Exception message is: " << message;
      XERCES_CPP_NAMESPACE::XMLString::release(&message);
      return false;
   }

   xercesc::SAX2XMLReader* parser =  xercesc::XMLReaderFactory::createXMLReader();
   parser->setFeature( xercesc::XMLUni::fgSAX2CoreValidation, true);
   parser->setFeature( xercesc::XMLUni::fgSAX2CoreNameSpaces, true);

   xercesc::DefaultHandler* defaultHandler = new CErrorHandler();
   xercesc::ContentHandler* h  = new CErrorHandler();

   xercesc::MemBufInputSource mis(reinterpret_cast< const XMLByte* >(XSD_SHEMA.c_str() ), XSD_SHEMA.size (), "/schema.xsd");
   xercesc::Wrapper4InputSource wmis (&mis, false);

   parser->loadGrammar (&wmis, xercesc::Grammar::SchemaGrammarType, true);
   parser->setFeature (xercesc::XMLUni::fgXercesUseCachedGrammarInParse, true);

   void* id = (void*)("file:///schema.xsd");
   parser->setProperty (xercesc::XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, id);

   parser->setContentHandler(h);
   parser->setErrorHandler(defaultHandler);

   try 
   {
      parser->parse(mXMLFilePath.c_str());
   }

   catch (const  xercesc::XMLException& toCatch) 
   {
      char* message =  xercesc::XMLString::transcode(toCatch.getMessage());
      std::cout << "Exception message is: "<< message << std::endl;;
      xercesc::XMLString::release(&message);
      return false;
   }

   catch (const  xercesc::SAXParseException& toCatch) 
   {
      char* message =  xercesc::XMLString::transcode(toCatch.getMessage());
      std::cout << "Exception message is: " << message << std::endl;;
      xercesc::XMLString::release(&message);
      return false;
   }

   catch (...) 
   {
      std::cout << "Unexpected Exception" ;
      return false;
   }

   delete parser;
   delete defaultHandler;
   return true;
}

我正在尝试使用 Xerces lib 在 C++ 中使用字符串 XSD_SHEMA 中的路径 mXMLFilePath 和 xsd 模式验证 xml 文件。 我创建了 CErrorHandler 类并对其进行了初始化,设置了架构 nolocation 参数以在 xml 路径中设置架构。 它建立了,但不起作用。有人有什么想法吗?

【问题讨论】:

    标签: c++ xml xsd xerces xerces-c


    【解决方案1】:
    #include <xercesc/sax2/SAX2XMLReader.hpp>
    #include <xercesc/sax2/XMLReaderFactory.hpp>
    #include <xercesc/sax/ErrorHandler.hpp>
    #include <xercesc/sax/SAXParseException.hpp>
    
    #include <xercesc/validators/common/Grammar.hpp>
    #include <xercesc/parsers/SAXParser.hpp>
    #include <xercesc/framework/MemBufInputSource.hpp>
    #include <xercesc/util/XMLString.hpp>
    
    #include <string>
    #include <iostream>
    
    class CErrorHandler : public xercesc::ErrorHandler 
    {
    public:
       /** Warning message method */
       void warning(const xercesc::SAXParseException& ex);
       /** Error message method */
       void error(const xercesc::SAXParseException& ex);
       /** Fatal error message method */
       void fatalError(const xercesc::SAXParseException& ex);
       /** Errors resetter method */
       void resetErrors();
    private:
       /** Based message reporter method */
       void reportParseException(const xercesc::SAXParseException& ex);
    };
    void CErrorHandler::reportParseException(const xercesc::SAXParseException& ex)
    {
       char* message = xercesc::XMLString::transcode(ex.getMessage());
       std::cout << message << " at line " << ex.getLineNumber() << " column " << ex.getColumnNumber() << std::endl;
    
       xercesc::XMLString::release(&message);
    }
    
    void CErrorHandler::warning(const xercesc::SAXParseException& ex)
    {
       reportParseException(ex);
    }
    
    void CErrorHandler::error(const xercesc::SAXParseException& ex)
    {
       reportParseException(ex);
    }
    
    void CErrorHandler::fatalError(const xercesc::SAXParseException& ex)
    {
       reportParseException(ex);
    }
    
    void CErrorHandler::resetErrors()
    {
    }
    
    
    
    class CXmlValidator
    {
    public:
       /** Constructor method */
       CXmlValidator();
       /** Xml file setter method */
       void setFilePath(const std::string &filePath);
       /** Destructor method */
       ~CXmlValidator();
       /** Xml file with schema validation method */
       bool validateSchema();
    private:
       /** Xml file */
       std::string mXMLFilePath;
    };
    
    
    CXmlValidator::CXmlValidator():
       mXMLFilePath("")
    {
    }
    
    CXmlValidator::~CXmlValidator()
    {
    }
    
    void CXmlValidator::setFilePath(const std::string &filePath)
    {
       mXMLFilePath = filePath;
    }
    
    bool CXmlValidator::validateSchema()
    {
       std::cout << std::endl;
       xercesc::XMLPlatformUtils::Initialize();
    
       std::string xsdFile = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>...";
    
       xercesc::SAX2XMLReader *parser = xercesc::XMLReaderFactory::createXMLReader();
       xercesc::ErrorHandler *handler = new CErrorHandler();
    
       xercesc::MemBufInputSource inMemorySchemaSource(reinterpret_cast<const XMLByte*>(xsdFile.c_str()), xsdFile.size (), "/schema.xsd");
    
       parser->loadGrammar(inMemorySchemaSource, xercesc::Grammar::SchemaGrammarType, true);
       parser->setFeature(xercesc::XMLUni::fgXercesUseCachedGrammarInParse, true);
       parser->setFeature(xercesc::XMLUni::fgSAX2CoreValidation, true);
       parser->setFeature(xercesc::XMLUni::fgSAX2CoreNameSpaces, true);
       parser->setProperty(xercesc::XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, const_cast<void*>(static_cast<const void*>("")));
       parser->setErrorHandler(handler);
       parser->parse("file.xml");
    
       if (parser->getErrorCount() != 0)
       {
          std::cout << "ERROR: XML file '" << mXMLFilePath << "' not confirm to the schema" << std::endl;
          return false;
       }
       else
       {
          return true;
       }
    }
    

    这是错误处理程序和验证器类的正确实现,如果有人需要的话

    【讨论】:

      【解决方案2】:

      Xerces 库(用于解析和加载语法)可以处理输入源(也就是实现 InputSource 接口的类)。 MemBufInputSource 将是某些仅存在于内存中的情况的类。

      XMLPlatformUtils::Initialize();
      XercesDOMParser* domParser;
      
      domParser = new XercesDOMParser();
      
      char *str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\"> \r\n </xs:schema>";
      
      std::string strContent = str;
      
      xercesc::MemBufInputSource pMemBufIS((XMLByte*)strContent.c_str(), 
      strContent.size(), "xsd");
      
      
      if (domParser->loadGrammar(pMemBufIS, Grammar::SchemaGrammarType) == NULL)
      {
          fprintf(stderr, "couldn't load schema\n");
          return false;
      }
      
      domParser->setValidationScheme(XercesDOMParser::Val_Auto);
      domParser->setDoNamespaces(true);
      domParser->setDoSchema(true);
      domParser->setValidationConstraintFatal(true);
      domParser->setExternalNoNamespaceSchemaLocation("C:\\User\\b.xsd");
      domParser->setValidationConstraintFatal(true);
      
      domParser->parse("file.xml");
      if (domParser->getErrorCount() == 0)
          printf("XML file validated against the schema successfully\n");
      else
          printf("XML file doesn't conform to the schema\n");
      

      【讨论】:

      • 这个解决方案正是我在寻找一种通过内存而不是 .xsd 文件将模式加载到 xerces 的方法时所寻找的解决方案。感谢您提供一个简单而优雅的示例。完美解决了我的问题。
      猜你喜欢
      • 2011-08-17
      • 2011-05-31
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      • 2019-02-15
      • 2012-08-24
      • 2014-03-27
      相关资源
      最近更新 更多