2007년 03월 13일
[미완성] Xerces C++ 사용하기 - XML Parser - DOM Model
Overview
Xerces C++ Parser를 사용하기 위한 환경 설정은 이전 SAX Model 활용 예에서 설명했었다.
이 글에서는 XML 문서를 처리하는 또 다른 방법인 DOM(Document Object Model)에 대해 설명한다. DOM은 XML 문서를 Object의 Tree로 표현하여 처리하는 방법이다. XML 문서를 구성하는 각 Element(Tag)들은 Tree의 노드로 표현되며, 전체 문서가 하나의 Tree로 나타난다. DOM에서는 XML 문서 전체를 메모리에 저장하기 때문에 메모리 소모량이 많다는 문제가 있으나, Tree 구조를 이용한 Random Access가 가능하고, 읽기와 쓰기를 모두 지원한다는 장점이 있다.
(SAX Model에서는 읽기(Parsing)만 지원된다.)
(전문가의 말에 따르면 XML 문서를 저장하기 위한 메모리 공간은 실제 XML 문서 크기의 약 7배 정도가 된다고 한다. 즉, 100MB짜리 XML 문서를 DOM 모델에서 처리하기 위해서는 700MB의 메모리 공간이 필요한 것이다. 따라서 DOM 모델에서 작은 용량의 메모리를 이용하여 XML 문서를 처리하기 위한 많은 연구들이 행해지고 있다.)
0. DOM 모델의 특징
DOM 모델도 SAX 모델과 마찬가지로 XML 문서를 다루기 위한 API들의 집합체이다. 다만 Random Access가 가능한 모델이어서 XML 문서를 Parsing할 뿐만 아니라 API를 사용하여 XML 문서를 생성하는 것도 가능하다.
SAX2 모델에서와 마찬가지로, DOM 모델도 항상 XMLPlatformUtils::Initialize() 함수 호출에서 시작하여, XMLPlatformUtils::Terminate() 함수 호출로 끝난다. Xerces를 사용할 때에는 항상 초기화를 수행한 후 사용하고, 마지막에 종료 함수를 호출해 주어야 한다.
DOM 모델은 스스로의 기능을 DOMImplementation이라는 오브젝트로 제공한다. DOM을 이용하는 코드는 제일 먼저 DOMImplementation 객체에 대한 포인터를 얻어오는 것에서 시작한다.
예를 들어, XML 문서를 하나 작성한다고 하면, 그 시작은 다음과 같다.
------------------------------------------------------------------------------------------
// Initialize Xerces Library Operation.
1: XMLPlatformUtils::Initialize();
// Create a new XML document (initially empty).
2: DOMImplementation *pImpl = DOMImplementation::getImplementation();
3: DOMDocumentType *pDocType = pImpl->createDocumentType(L"svg", NULL, NULL);
4: DOMDocument *pDoc = pImpl->createDocument(L"svg", L"svg", pDocType);
------------------------------------------------------------------------------------------
1번 코드는 앞서 설명했듯이, Xerces 라이브러리를 초기화하는 부분이다.
2번 코드는 DOM 모델을 사용하기 위해 DOMImplementation 객체에 대한 참조 포인터를 얻어오는 부분이다. 이 객체를 통해 3번, 4번 코드에서 DOMDocumentType 객체와 DOMDocument 객체를 생성한다. 4번 코드에서 생성되는 pDoc 객체가 실제 XML 문서를 저장하게 된다.
1. Xerces DOM 모델을 이용하여 XML 문서를 파싱하기
SAX2 모델에서와 마찬가지로, DOM 모델도 항상 XMLPlatformUtils::Initialize() 함수 호출에서 시작하여, XMLPlatformUtils::Terminate() 함수 호출로 끝난다. XML 문서의 Parsing은 XercesDOM Parser를 이용하여 수행하는데, 다음 코드와 같이 XercesDOMParser 객체를 생성하고, 해석할 XML 문서 파일 이름을 입력으로 주면 된다. 세세한 설정 함수들은 일단 무시하기 바란다. 파싱이 끝나면 해당 XML 파일은 DOM Tree 형태로 메모리에 저장된다. 이 DOM Tree는 parser->getDocument() 함수 호출을 통해 얻을 수 있다.
-------------------------------------------------------------------------------
<Code Listing>
// DOM Parser 객체 생성
XercesDOMParser *parser= new XercesDOMParser;
// Check proper creation of the parser
// 프로그래머는 항상 에러가 발생할 상황에 대비해야 한다 ^^;
if(!parser)
{
// Parser creation failed.
std::cerr << "Parser creation failed" << std::endl;
return 0;
}
// Parser creation successful.
parser->setDoSchema(false);
parser->setDoNamespaces(false);
parser->setValidationScheme(XercesDOMParser::Val_Auto);
parser->setCreateEntityReferenceNodes(false);
// Do parsing
try
{
xmlFile = "test_data.xml"; // 해석할 XML 문서 파일 이름
parser->parse(xmlFile); // Parsing 수행
}
catch (...)
{
}
// 해석된 XML 문서의 DOM Tree 얻어오기
DOMDocument *XmlDoc = parser->getDocument();
...
------------------------------------------------------------------------------
위의 코드에서 볼 수 있듯이 XML 문서의 Parsing은 의외로 간단하다.
2. DOM 모델로 표현된 XML 문서를 화면에 출력하기.
가장 간단한 방법은 Xerces 라이브러리가 제공하는 출력 기능을 사용하는 것이다. Xerces는 DOM Tree로 표현된 XML 문서를 파일이나 Stdout으로 출력할 수 있는 방법을 제공한다.
Xerces가 제공하는 출력 기능을 사용하여 XML 문서를 화면에 출력하는 방법은 다음과 같다.
-------------------------------------------------------------------------------------
// print out parsed XML.
1: DOMImplementation *pImpl = DOMImplementation::getImplementation();
2: DOMWriter *pSerializer=pImpl->createDOMWriter();
3: XMLFormatTarget *pTarget=new StdOutFormatTarget();
// Set up serializer parameters.
4: pSerializer->setNewLine(L"\n");
// set feature if the serializer supports the feature/mode
5: if ( pSerializer->canSetFeature(XMLUni::fgDOMWRTSplitCdataSections, false) )
pSerializer->setFeature(XMLUni::fgDOMWRTSplitCdataSections, false);
if ( pSerializer->canSetFeature(XMLUni::fgDOMWRTDiscardDefaultContent, false) )
pSerializer->setFeature(XMLUni::fgDOMWRTDiscardDefaultContent, false);
// turn off serializer "pretty print" option
if ( pSerializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, false) )
pSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, false);
if ( pSerializer->canSetFeature(XMLUni::fgDOMWRTBOM, false) )
pSerializer->setFeature(XMLUni::fgDOMWRTBOM, false);
// Turn on pretty print option.
if (pSerializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true) )
pSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
// output to standard out.
6: pSerializer->writeNode(pTarget, *(parser->getDocument()));
-----------------------------------------------------------------------------------------
1번 코드는 DOM 모델을 사용하기 위해 DOMImplementation 객체에 대한 참조 포인터를 얻어오는 부분이다. 2번 코드는 XML 문서를 출력하기 위해 DOMWriter라는 객체를 생성하는 코드이고, 3번 코드는 XML 문서를 출력할 장치를 지정한다. 우리는 Stdout 장치에 XML 문서를 출력하기를 원하므로 StdOutFormatTarget 객체를 생성하였다. 4번/5번 코드는 XML 출력 형식을 다듬기 위해 각종 DOMWriter의 설정을 처리하는 부분이다. (일단은 중요하지 않으므로 무시해도 된다).
실제로 Parsing된 문서를 stdout에 출력하는 코드는 6번 코드이다. pTarget은 StdOutFormatTarget 객체를 가리키고, parser->getDocument()는 Parsing된 XML 문서를 가리킨다. 6번 코드의 의미는 설정된 형식대로 Parsing된 XML 문서를 pTarget으로 (Stdout장치로) 출력하라는 것이다.
3. DOM 모델로 표현된 XML 문서를 Traversing 하기
(아직 작성 중)
# by | 2007/03/13 14:03 | c/c++/mfc | 트랙백 | 덧글(1)





☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
저는 Dom Tree가 xml 파일로 정상적으로 생성은 잘됩니다 웹브라우저로 보면 트리도 잘나오긴한데
이걸 편집하려고 텍스트 편집기로 열어보면 아래 처럼 한줄씩 빈줄이 항상 포함되어있던데
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<company>
// 빈 줄이 항상 생김
<product>Xerces-C</product>
// 빈 줄이 항상 생김
<category idea="ABC">XML Parsing Tools</category>
// 빈 줄이 항상 생김
<developedBy>Apache Software Foundation</developedBy>
// 빈 줄이 항상 생김
</company>
serializer->getDomConfig()->setParameter 으로 이것저것 속성 계속 바꿔봐도 안되고
serializer->setNewLine 으로도 공백을 주나 '\n'을 주나 "\r\n"을 주나 마찬가지던데
님은 이문제를 어떻게 해결하셨는지 궁금합니다