본문 바로가기

programming/java

SAX split the data element problem


SAX

Simple API for XML

xml로 된 파일 및 문자를 해석할 수 있게 해주는 응용프로그램인터페이스(API).

SAX가 어떤 녀석인지, DOM과의 차이점은 무엇인지에 대해 많겠지만 얕은 지식으로 똥냄새나는 글 싸지르는거 보단

http://en.wikipedia.org/wiki/Simple_API_for_XML

위키 참고하는게 보는 분들 정신건강에 나을듯 싶어 따로 적진 않겠음.

간단하게 DOM의 경우 문서 단위로 해석하는 반면 SAX의 경우 line단위로 해석함.


SAX의 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// node 값 인식시 발생
    public void characters (char ch[], int start, int lengththrows SAXException{
        data = escapeData(ch, start, length);
        //개행, Tab, 캐리지리턴 문자 제외
        if(data.indexOf("\\n")==0 || data.indexOf("\\t")==0 || data.indexOf("\\r")==0){
            // System.out.println("  EVENT: " + data + " Deleted.");
        }else{
            /* SAX PARSER Character Buffer Size(2048)가 max초과시 초기화 되면서
                     data element가 split되는 현상 방어로직*/
            if(beforeBufferFilledSize != 2048){
                saxTempStr="";
            }
             // log.debug(nodeName);
             /* log.debug("Buffer Start Position:["+start+"],Character Length:{"
                      +length+ "},Start+Length:("+(start+length)+"),[Character:"+data+ ",saxTempStr:"
                      +saxTempStr+"]");*/ // DEBUG TEST용
             if((start+length)==2048){
                saxTempStr = data;
            }
            if(start==0&&beforeBufferFilledSize==2048){
                fullDataStr = saxTempStr+data;
                map.put(nodeName.trim(),fullDataStr.trim());
            }else{
                if(beforeNodeName.equals(nodeName)){
                    fullDataStr = map.get(nodeName).toString()+data;
                    map.put(nodeName.trim(),fullDataStr.trim());
                }else{
                    fullDataStr = data;
                    map.put(nodeName.trim(),fullDataStr.trim());
                }
                
            }
            beforeBufferFilledSize=(start+length);
            beforeNodeName=nodeName;
        }
    }
 

위와같이 characters 메쏘드로 node안의 element를 인식하는데,

이때 SAX parser의 경우 한번에 2048byte 만큼밖에 인식하지 못함.

물론, 2048을 다 채우고 나면 버퍼를 싹 비우고 다시 0부터 채워나감.

하지만 버퍼를 비우고 새로 채워나가는 과정에서 문제가 생김.


상황

1. 새로운 element 인식시 2045부터 채워질 차례

2. 새로 채워질 element의 경우 길이가 4일경우(ex>null)

3. 남은 여유분이 2048-2045 = 3으로 가용공간은 3

4. 이에 SAX의 경우 임의로 element를 3만큼 잘라버림

5. 이때 Programmer가 예측못한 상황이 발생되어 데이터의 정합성에 문제가 생김

 

예시(Problem)

-SAMPLE XML

<variable>null</variable>

-정상 CASE

start : 1196

length : 4

nodeName : variable

data(element) : null

-비정상 CASE(MAX BUFFER SIZE 2048 PROBLEM)

start : 2045

length : 3

nodeName : variable

data(element) : nul

start : 0

length : 1

nodeName : variable

data(element) : l

 

SOLUTION

위의 예시를 살펴보면 문제 상황에서 버퍼사이즈가 2048이후 0으로 초기화.

또한, nodeName이 동일하게 리턴되는 것을 확인할 수 있음.

이에,

1. 이전 버퍼사이즈가 2048이고 버퍼 시작이 0인 경우이전 텍스트와 현재 characters 메쏘드에서 인식된 텍스트를 붙여줌.

2. 1번케이스가 아니라고 하더라도(saxParser의 경우 line by line으로 분석하지만 xml리딩이 순차적이지 않아, 문제상황이 1번케이스에 걸리지 않을 수도 있음) 이전 nodeName과 현재 nodeName이 같은 경우 문제 상황이라고 보고 1번과 같은 처리.


 


Thx for advice

http://rb-techtips.blogspot.kr/2012/08/sax-2048-byte-issue-on-java-xml-parsing.html

'programming > java' 카테고리의 다른 글

더블서밋방지 및 뒤로가기 후 서밋방지 Token Util(TokenMngUtil)  (2) 2013.09.13
Javadoc Tutorial  (0) 2013.05.16
refactoring  (0) 2013.01.09