使用xerces c ++中的内存模式进行xml文件验证

时间:2014-03-21 17:10:18

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

#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类并对其进行了初始化,设置了schema nolocation参数,以便不在xml路径中设置为schema。 它建立了,但没有工作。有人有什么想法吗?

2 个答案:

答案 0 :(得分: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;
   }
}

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

答案 1 :(得分:0)

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");