'DOM'에 해당되는 글 1건

  1. 2010.04.04 [펌]DOM을 이용한 메타데이터 추출(JAVA)
프로그래밍/XML2010. 4. 4. 18:05

DOM을 이용한 메타데이터 추출             
                                                                                                                        
                                                                                              

작성자 : 김 인희(kevin@asc.co.kr)

Summary
일반적으로 웹사이트 구축시 테이블 이름이나 sql구문 또는 여러 (사용자가 정의한)코드값들을 그대로 코드에 집어 넣는다. 그리고 웹페이지에서 보여지는 여러 텍스트들도 그대로 코드에 넣는 경향이 있다. 물론 소규모의 프로젝트시에는 문제가 없으나 프로젝트가 커질수록 웹사이트를 유지, 보수하기가 어려워진다. 그래서 xml과 자바를 연동시켜서 위에서 나열한 메타 데이터를 얻는 방법을 소개할까 한다.

---------------------------------------------------------------------------------------------------------


xml은 단지 데이터이기 때문에 xml을 처리하기 위해서는 파싱 과정이 필요하다. 따라서 xml을 사용하는 애플리케이션은 각각의 데이터에 접근하고 처리하기 위한 수단이 필요하다. 그러한 기능을 가지고 있는 것이 SAX와 DOM이다.


SAX 
SAX는 'Simple API for xml'을 의미하며, 그 이름 그대로 xml을 위한 간단한 API를 제공한다. SAX는 xml 데이터를 분석하기 위한 이벤트 기반의 구조를 제공하며, 이러한 구조는 크게 문서를 읽어나가는 과정과 데이터를 사용할 수 있는 부분으로 분리된다. 이벤트는 xml 문서를 순차적으로 처리하는 동안 각 단계에서 발생하며, SAX는 각 이벤트가 발생할 때 호출되는 메소드를 정의하고 있다. 예를 들어, 한 요소의 여는 태그를 만날 경우 startElement() 메소드를 호출하며, 끝 태그를 만날 경우 endElement() 메소드를 호출한다.
SAX는 문서를 읽어나가는 과정에서 발생하는 이벤트를 위한 인터페이스 뿐만 아니라, 잘못된 문서나 비적격(non well-formed) 문서와 같이 xml을 분석하는 과정에서 발생할 수 있는 다양한 상황을 처리할 수 있도록 해 주는 에러와 경고 집합을 정의하고 있다.

 

DOM  
DOM은 'Document Object Model'을 의미한다. SAX가 단지 xml 문서의 데이터에 접근하기 위한 방법을 제공한다면, DOM은 그러한 데이터를 처리하는 방법을 제공하기 위해 설계되었다. DOM은 xml 문서를 트리 형태로 표현한다. 자바를 비롯한 프로그래밍 언어에서는 트리 구조를 쉽게 순회하고 처리할 수 있기 때문에, DOM 트리(xml 문서를 DOM으로 표현한 것을 DOM 트리라고 부른다)를 쉽게 처리할 수 있다. SAX와 달리 DOM은 전체 xml 문서를 메모리에 읽어온 후에 DOM 트리를 구성하기 때문에, 한번 문서를 읽으면 매우 빠르게 전체 문서에 접근할 수 있다.
DOM이 전체 xml 문서를 메모리에 읽어온 후에 DOM 트리를 작성한다는 것이 빠르게 xml 문서의 각 요소에 접근할 수 있다는 장점을 제공하긴 하지만, 반면에 결정적인 단점을 제공하기도 한다. DOM은 xml 문서의 크기에 비례한 메모리를 필요로 하기 때문에, xml 문서의 크기가 커질수록 많은 메모리를 요구하게 된다. xml 문서의 매우 클 경우 이는 매우 많은 양의 시스템 자원을 사용하게 되며, 따라서 시스템의 전체적인 성능 저하 현상을 일으키기도 한다
먼저 각종 코드값을 가지고 있는 xml 문서를 살펴보자.

 

xml 문서(codeSubset.xml)


<?xml version = "1.0" encoding="EUC-KR"?>
<Config> 
 <TableCode>
             <Table code="111">CounselData</Table>
             <Table code="222">KcabBoard</Table>
 </TableCode>
 <JobList>
             <Job code="50">전체</Job>
             <Job code="51">법조계</Job>
   <Job code="52">실업계</Job>
             <Job code="53">학계</Job>
 </JobList>
</Config>

 

코드는 각 엘리먼트의 속성값에 넣었다. 그리고 코드값은 엘리먼트의 양쪽 태그사이에 두었다. xml1.0 스펙에 따르면 태그 사이에 있는 데이터는 문자데이터(character data)이다. 
다음으로 위 xml 문서를 처리해서 코드에 해당하는 코드값을 얻어오는 프로그램을 작성해보자. 여기서는 DOM을 이용할것이다. xml 파 서로는 Apache Xerces(<
http://xml.apache.org>) 파서를 사용하였다. Xerces 파서를 다운 받은다음 클래스패스에 추가하면 된다. 
다음 코드를 살펴보자. 


import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document; 
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.CharacterData;
//import org.apache.xerces.dom.TextImpl;


public class xmlMgr {
           /*
           * 주어진 xml를 찾아 파서로 파싱을 하고 Document를 리턴한다
           */
           private Document getDocument(String uri) {
                       System.out.println("Parsing xml file: "  + uri + "\n");
                       
                       DOMParser parser = new DOMParser();
                       Document doc = null;
                       
                       try {
                                   parser.parse(uri);
                                   doc = parser.getDocument();
                                   
                       } catch(Exception e) {
                                   System.out.println("Error in Parsing : " + e.getMessage());
                       }
                       return doc;
                       
           }
           /*
           * @param uri xml 문서가 위치한 URL
           * @param nodeName 노드 이름
           * @param codeValue 코드값
           */
           public String getConfig(String uri, String nodeName, String codeValue) {
           
                       NodeList nodeList = getNodeList(uri, nodeName);
                       
                       String returnValue = "";
                       /*
                       * 각 노드에 해당하는 속성을 가지고 있는
                       * NamedNodeMap를 얻고 코드에 해당하는 
                       * 코드값을 얻는다
                       */
                       if(nodeList != null) {
                                   for(int i = 0; i < nodeList.getLength(); i++) {
                                               Node node = nodeList.item(i);
                                               NamedNodeMap attributes = node.getAttributes(); 
                                               for(int j = 0; j < attributes.getLength(); j++) {
                                                           Node current = attributes.item(j);
                                                           if(current.getNodeValue().equals(codeValue)) {
                                                                       returnValue = getValue(node.getChildNodes());
                                                           }
                                                           
                                               }
                                   }
                       }
                       return returnValue;            
                                   
           }
           
           private String getValue(NodeList children) {
                       
                       String returnValue = "";
                       if(children != null) {
                                   for(int i = 0; i < children.getLength(); i++) {
                                               returnValue = children.item(i).getNodeValue();
                                   }
                       }
                       return returnValue;
                       
           } 


           /*
           * 주어진 파일이름에 해당하는 Document를 통해
           * 노드이름과 일치하는 NodeList를 얻는다.
           */
           private NodeList getNodeList(String uri, String nodeName) {
                       
                       NodeList returnNodeList = null;
                       Document doc = getDocument(uri);
                       returnNodeList = doc.getElementsByTagName(nodeName);
                       return returnNodeList;
                       
           }

 

코드 중간 중간에 주석을 삽입했기 때문에 이해하는데 어려움은 없을 것이다. 실제로 위와 같은 방법은 상당히 유용한다. 만약
테이블 이름을 얻는다면 다음과 같이 하면 된다.

 

           xmlMgr objxmlMgr = new xmlMgr();
           String tableName = objxmlMgr.getConfig("codeSubset.xml", "Table", "111");

 

그러면 tableName는 "CounselData"를 얻을 것이다.

또 jsp내에서 코드값에 해당하는 텍스트를 얻을때도

 

           <%=objxmlMgr.getConfig("codeSubset.xml", "Job", "51")%>

 

이러한 방법을 사용하면 된다. 


자바와 xml을 연동함으로써 그동안 개발자에게 골치거리였던 유지, 보수 문제를 어느 정도 해결할 수 있다. 앞으로 자바와 xml연동
을 더 효과적으로 한다면 보다 향상된 웹애플리케이션을 작성할 수 있을 것이다.

 

Resources
           * javacan 페이지
                       (<
http://www.javacan.com>)
           * Java and xml (o'reilly)
           * xml Applications(Wrox)

 

궁금한 점이나 고쳐야 할 부분이 있으면 위의 메일 주소로 멜 날려 주세요.

Posted by 컴투