보통 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;
}