본문 바로가기

학습컨텐츠/XML

XML다루기 - 5. 만들어진 XML 문서 알맞게 처리하기

5-1. 파싱(Parsing)이란?

지금까지 우리는 DTD를 이용해 새로운 마크 업 언어를 개발하는 방법과, 개발된 마크 업 언어를 가지고 XML 문서를 작성하는 방법에 대해 공부했습니다.

이렇게 작성된 XML 문서를 어떻게 하면 본래의 목적에 맞게 사용할 수 있을까요? 즉, 데이터를 효과적으로 관리하고 처리하려는 목적에 맞게 말입니다.

그것을 위해 응용프로그램과 XML 파서(Parser)가 존재합니다. 응용프로그램(Application Program)은 data를 알맞게 쓰고자 하는 프로그램이고, XML으로 구성된 data들을 응용프로그램이 유용하게 쓰기 좋은 형태로 만들어주는 것이 바로 XML파서입니다.



<XML 문서 처리 과정>

파싱이란 무엇일까요? 사실 파싱을 한글로는 정확히 번역할 수가 없기 때문에 쉽게 이해하기 힘들 것입니다. 굳이 알맞은 번역을 찾자면 정제하기, 해석하기 가 적당할 것 같습니다. 파싱이란 어떤 일정한 문법을 토대로 나열된 data들을 그 문법에 맞게 분석하여 새롭게 구성하는 작업을 뜻합니다.


즉 어떤 data를 파싱한다는 것은 크게 두 가지를 의미합니다.

첫 째, 파싱하는 data가 특정 문법에 알맞게 정리된 data인지 확인하는 것을 뜻합니다.

둘 째, 파싱하는 data를 응용프로그램이 목적에 맞게 이용하기 쉬운 형태로 구성해 주는 것을 뜻합니다.

위와 같은 목적을 위해서 파서는 파싱하고자하는 data와 그 data의 토대일 것이라고 생각되는 문법을 알고 있어야 합니다.

 



 

5-2. XML 문서 파싱하기 (SAX와 DOM의 원리)

파싱에 대해 대충 알았으니 이제 XML 문서를 파싱하는 방법에 대해 알아봅시다.

XML문서를 파싱하는 방법은 크게 두 가지가 있습니다. SAX(Simple API for XML) 방식과 DOM(Document Object Model)방식입니다. (API=Application Programming Interface)


이 두 가지 방식의 차이점은 data를 파싱할 때 output으로 나오는 잘 정제된 data를, 응용프로그램이 언제 사용하느냐에 달려있습니다.

Tree를 만들어가는 도중(즉, parsing 도중) 응용프로그램이 하고자 하는 작업을 수행하기 위해 data를 이용한다면, 그 방식은 SAX방식이고,

Tree를 만든 후에, 응용프로그램이 그 Tree를 이용해 작업을 수행한다면 그 방식은 DOM방식인 것입니다.


파싱 방식이 두 가지라는 것은 파서가 두 가지라는 얘기는 아닙니다. 예를 들어 DOM방식을 지원하는 파서에는 MSXML, Xerces, JAXP 등등이 있습니다. 중요한 것은 이 모든 파서가 DOM방식으로 파싱을 할 경우에 결국 만들어내는 결과물은 모두 동일한 방식으로 access될 수 있는 객체(혹은 Interface)라는 것입니다. 즉, 어떤 파서를 쓰든지 응용프로그램은 신경 쓸 필요가 없고, 동일한 방식으로 접근할 수 있는 것입니다.

이것이 바로 DOM, SAX와 같은 규격이 존재하는 이유입니다. 만일 규격이 존재하지 않는다면 파서마다 제 각각의 Tree가 나올 것이고, 따라서 그 tree를 이용하는 것도 제각각 일 것입니다. 하지만, 규격이 있음으로 해서, 어떤 파서를 쓰든지 같은 Tree가 나오므로 우리는 파서에 독립적인(independent) 데이터 처리를 할 수 있는 것입니다.

그러나, 파싱 결과로 나오는 Tree(객체 형태)가 규격에 의해 정해져 있다고 해서 실제로 java, VB, Python등의 언어를 이용해 Tree(객체 형태)에 접근할 때 똑같은 함수를 쓰지는 않습니다. 다시 말하면, 어떤 언어든지 Tree(객체 형태)에 접근 할 때, 결국 따지고 보면 같은 Tree로 접근하는 것이지만, 사용 언어에 따라 그것이 서로 달라 보인다는 것입니다. (함수 이름이라든지, argument등등의 것들) 그것은 java, VB, Python 등 각 언어 안에 Tree에 접근하기 위한 API가 각각 따로 존재하기 때문입니다.

정리하자면 java, VB, Python을 사용하는 프로그래머는 서로 다른 형태의 API를 통해 Tree에 접근하지만, 사실 java, VB, Python내부에 구현되어있는 Tree접근 API는 동일한 DOM interface를 사용한다고 할 수 있습니다.

 






5-3.
XML 문서 Parsing하기 (파이썬을 이용한 파싱)

이제, 우리가 사용할 언어인 파이썬에서 XML을 파싱하고 이용하는 방법을 알아보도록 합시다. SAX 방법에 대해서만 알아보도록 하지요. 아까 말했듯이 SAX방식은 Tree를 만드는 동시에(즉, 파싱을 하는 동시에) 필요한 data들을 처리하는 방식입니다.

이 방식은 파서가 XML을 파싱하면서 어떤 이벤트가 발생할 때마다 프로그래머가 원하는 작업을 수행하게 되는데요. 그래서 이벤트 기반의 인터페이스라고도 불립니다. 이벤트 목록은 SAX라는 interface안에 이미 정의되어 있는 것이고요, 프로그래머가 할 일은 이벤트 발생시에 처리할 작업, 즉 event handling을 구현하는 것입니다.


Data 파싱단계는 크게 3단계로 나누어 생각하면 쉽습니다.

1) 파서 객체 만들기
2) 핸들러 만들기
3) 파싱하기


각 단계를 간단한 예시를 통해 살펴보도록 하지요.

1) 파서 객체 만들기

>>> from xml.sax import make_parser
>>> parser = make_parser()

위와 같이 python 코딩으로써 parser라는 변수에 parser객체를 instance화 시킵니다. 이제 우리는 parser라는 객체의 함수를 이용해 특정 xml파일을 parsing할 수 있습니다.


2) 핸들러 만들기

>>> from xml.sax import handler
>>> class Myhandler(handler.ContentHandler):
def startElement( self, name, attrs):
print 'Start Tag:', name

위의 코딩은 handler.ContentHandler라는 클래스를 상속받아서 그 안에 startElement라는 메쏘드를 등록한 것입니다. startElement는 시작 태그가 읽혔을 때 호출되는 메쏘드 입니다. 즉, 위의 예시에서 우리는 print 'Start Tag:', name라는 코딩을 해주었으므로 파싱을 하면서 매번 시작 태그가 읽힐 때, Start Tag: (태그이름) 을 출력하라는 의미를 가집니다.

이제 우리는 이 핸들러를 처음에 만들었던 parser 객체에 등록해 줍니다.

>>> h=Myhandler()
>>> parser.setContentHandler(h)


3) 파싱하기

>>> parser.parse('names.xml')

위와 같이 parse명령을 내리면, names.xml을 파싱하면서 이벤트가 발생할 때마다 우리가 정의해주었던 handler대로 작업을 수행하게 됩니다.

만일 names.xml이란 xml파일이

<names>
    <name x= "y">
    Lee
    </name>
    <name x= "y">
    Kim
    </name>
</names>

와 같이 주어졌었다면

>>> parser.parse('names.xml')

후의 결과는

Start Tag: names
Start Tag: name
Start Tag: name

위와 같은 문단의 출력일 것입니다.


지금까지 XML이 무엇인지? 그리고 어떻게 사용하는 것인지에 대해 배웠습니다. 이제 우리의 처음 궁금증으로 돌아가서 XML의 장점이 무엇인지? 왜 우리가 XML을 사용해야 하는지? 한번 알아볼까요?