본문 바로가기

프로그래밍 언어/Java

Java) 정규식과 StringBuffer를 이용하여 문자열 특정 위치만 치환하기

눈으로 확인하기에는 방대한 양의 XML에서 특정 범위를 다른 형식으로 만들어 치환하는 일이 필요했는데 그냥 replace를 하려니 특정 범위가 XML 내에서 중복되는 경우 마지막에 replace 되는 형태로 일괄 변경되었다. 처음에는 그냥 docx로 열리지 않아서 뭐가 문젠지 한참 살펴봤다. 문제는 유니크해야 하는 아이디가 중복되어 오류가 발생하는 것! array와 set에 각각 담아 확인해 보았더니 둘의 개수가 다른 것으로 보아 특정 범위가 중복되는 것들이 있었다!! 그래서  치환하기 전에 특정 범위에 사용되는 rsid를 모두 유니크 하게 만들어주기로 했다. 뽑아서 유니크하게 만들어 주어야 하는 부분의 형식이 정해져있기 때문에 정규식으로 뽑고, 뽑힌 결과의 정확한 위치를 알아내서 String buffer로 해당 부분만 유니크 값으로 바꾸어 주는 것! 

 

/**
 * 중복 rsid 처리 
 * @param xml
 * @return xml without duplicate rsid
 */
private String handleDuplicateRsid(String xml){
    Pattern p = Pattern.compile("w:rsidRPr=\"(.*?)\"");
    Matcher m = p.matcher(xml);
    Integer cnt = 0;
    StringBuffer sb = new StringBuffer(xml);

    while(m.find(cnt)){
        sb.replace(m.start(1), m.end(1), commentService.getRandom8BitHexString());
        cnt = m.end();
    }
    xml = sb.toString();
    return xml;
}

 

이렇게 한번 중복 rsid들을 처리해주고 replace 하니까 중복 comment id도 생기지 않아서 오류 안난다 ㅠㅠ 이것 때문에 하루 종일 삽질했네

 

** 여기서 comment id는 워드에 메모 기능을 위해 사용 하는 것인데 실제 xml에서는 코멘트 단 부분을 <w:commentRangeStart w:id="*" /> ... <w:commentRangeEnd w:id="*" />로 감싸 주고 comment 에 남긴 텍스트나 작성자, 작성일자 등의 정보는 패키지 형태로 문서의 가장 아래 별도 태그 내에 <w:comments w:id="8"> ... </w:comments> 와 같은 형태로 정보를 저장하고 있다. 물론 이거 말고도 commentsIds, commentsExtended, commentsExtensible 등에 메모 확인 과 같은 정보가 더 많이 분산 저장 되어 있다. 이 프로젝트 말고 XML을 이렇게 많이 사용할 일이 있을까 싶지만 이제 XML마스터가 된 것은 분명하다 ㅋㅋ