본문 바로가기

카테고리 없음

Xerces C에서 스키마 참조 없는 XML 문서에 대해 스키마 주고 validation 수행

보통 XML 문서에서는 DTD나 XSD를 참조할 수 있도록 해주는데,
그것이 없는 일반 문서를 DTD나 XSD 선언을 주고 이를 기준으로 유효성 검사를 수행하도록 하기 위한 방법을 찾아보려고 작성했던 sample code이다.
ps. 제발 매뉴얼 좀 잘 읽어보고 짜자고... ㅡㅡ^

/*
 * DTD 또는 스키마 참조가 없는 XML 문서를 DTD나 스키마를 지정하여
 * 유효성 검사를 수행할 수 있는 방법을 찾기 위해 작성된 예제 코드
 *        Dec 11, 2007
 *        from Bart
 */

#include <iostream>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/sax2/DefaultHandler.hpp>
#include <xercesc/util/XMLUni.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/validators/common/Grammar.hpp>
#include <iostream>

XERCES_CPP_NAMESPACE_USE

int main(int argc, char* args[]){
 std::cout << "Starting to validate an XML file with a DTD or an XMLSchema definition "<<std::endl;
 char* xmlFile = "personal.xml"; //XML 파일 이름
 char* dtdFile = "personal.dtd"; //DTD 파일 이름
 char* xsdFile = "personal.xsd"; //xsd 파일 이름

 XMLPlatformUtils::Initialize();

 SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();
 parser->setFeature(XMLUni::fgSAX2CoreValidation, true); //validation 수행 여부 true이면 XML 문서는 반드시 문법을 설정해 주어야 한다.
 parser->setFeature(XMLUni::fgXercesDynamic, false); //문법이 기술된 경우에만 validation을 수행한다.
 parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true); //NS의 처리
 parser->setFeature(XMLUni::fgXercesSchema, true); //XMLSchema의 지원 여부 
 parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true); //XMLSchema 선언 자체가 valid 한지 검사


 DefaultHandler* dh = new DefaultHandler();
 parser->setContentHandler(dh);
 parser->setErrorHandler(dh);


 /*
  * 아래의 property 설정은 XML 문서가 NS 선언과 함께 XSD 스키마 참조를 하는 경우를 함수로 설정하는 것이다.
  * e.g. XML 문서의 루트에서
  * <root xmlns:xsi="http:/www.w3.org/2001/XMLSchema-instance"
  *       xsi:schemaLocation="http://www.example.com
  *              personal.xsd">
  *  이 경우  xsi ns는 해당 XML 문서가 XS의 인스턴스임을 나타낼 뿐이며,
  *  실제 이 XML 문서의 NS는 schemaLocation 애트리뷰트 값 중 공백 문자로 구분되는 첫 URI http://www.example.com이 된다.
  *  그리고 해당 NS에 대한 스키마 정의는 공백 문자 다음의 personal.xsd이다.
  * 
  *  아래의 함수로 선언시에는  
  */
 //char* schLoc="www.example.com personal.xsd";
 //parser->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation, schLoc);

 /*
  * 아래의 함수는 schema를 참조하는 XML 문서가
  *  <root noNamespaceSchemalocation="personal.xsd">
  *  로 NS 없이 스키마 참조를 하는 것을 함수로 설정하는 것이다.
  *  더불어 DTD 에 대한 참조도 이와 동일하게 한다. (xsdFile 또는 dtdFile)
  */
 parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, xsdFile);

 // 아래의 함수들은 스키마 참조 설정과 아무런 관계가 없다.
 // 하나의 스키마 정의를 가지고 이를 따르는 많은 XML 문서들을 반복적으로 validation 수행 시
 // 속도 향상을 위해 DTD/XSD를 캐싱하기 위한 함수일 뿐이다.

 /* parser->loadGrammar(dtdFile, Grammar::DTDGrammarType, true);
 parser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true); 
 */
 try{
  parser->parse(xmlFile);
 }
 catch(const XMLException& toCatch){
  char* message= XMLString::transcode(toCatch.getMessage());
  std::cout << "Exception message is : "<<std::endl
     << message <<std::endl;
  XMLString::release(&message);
  return -1;
 }catch(const SAXParseException& toCatch){
  char* message =XMLString::transcode(toCatch.getMessage());
  std::cout << "Exception messsage is : " <<std::endl
   << message <<std::endl;
  XMLString::release(&message);
  return -1;
 }
 
 std::cout << "reading the XML file was finished"<<std::endl;
 delete parser;
 delete dh;
 return 0;

}