- Arawn's Dev Blog
- Outsider's Dev Story
- Toby's Epril
- Benelog
- NHN 개발자 블로그
- SK 플래닛 기술 블로그
- OLC CENTER
- 소프트웨어 경영/공학 블로그
- 모바일 컨버전스
- KOSR - Korea Operating System …
- 넥스트리 블로그
- 리버스코어 ReverseCore
- SLiPP
- 개발자를 위하여... (Nextree 임병인 수석)
- "트위터 부트스트랩: 디자이너도 놀라워할 매끈하고 직관…
- Learning English - The English…
- real-english.com
- 'DataScience/Deep Learning' 카테…
- Deep Learning Summer School, M…
- Deep Learning Courses
민서네집
how to pretty print xml from Java 본문
자바에서 xml 을 예쁘게 indent 해서 변환하려면...?
[출처] http://stackoverflow.com/questions/139076/how-to-pretty-print-xml-from-java
이미 검증된 xml 파일이라면 굳이 dom 으로 변환하지 않고, indent 만 넣어서 변환해주는 소스가 있다.
메모리도 아끼고, 속도도 빠를듯 하다.
여기 있는 코드를 가지고 돌려봤더니 line wrap 이 이상하게 동작했다.
나는 line wrap 기능을 쓰지 않고, synchronized 지시어를 빼도 되도록 멤버변수를 사용하지 않도록 코드를 수정했다.
또, 위 웹사이트에 있는 원래 코드는 한줄로 쭉 이어진 xml 에 대해서만 정렬이 되고, xml 노드마다 줄바꿈 문자가 들어간 경우라던지 어느 정도 indent 가 된 xml 에 대해서는 작동하지 않는다. 나는 이런 경우에 대해서도 똑같이 정렬이 되도록 코드를 수정했다.
수정한 코드는 다음과 같다.
package me.bryan7.util; /** * XML utils, including formatting. ** [출처] <a href='http://stackoverflow.com/questions/139076/how-to-pretty-print-xml-from-java'>http://stackoverflow.com/questions/139076/how-to-pretty-print-xml-from-java</a> */ public class XmlUtils { private static XmlFormatter formatter = new XmlFormatter(); private static final int DEFAULT_INDENT_NUM_CHARS = 4; public static String formatXml(String s) { if( s == null ) return s; return formatter.format(s, DEFAULT_INDENT_NUM_CHARS, 0); } public static String formatXml(String s, int initialIndent) { if( s == null ) return s; return formatter.format(s, DEFAULT_INDENT_NUM_CHARS, initialIndent); } private static class XmlFormatter {
// XML 노드의 값이 여기에 지정된 글자수가 넘어가면 노드와 같은 줄이 아니라 다음 줄에 표시된다. private static final int SINGLE_LINE_CHAR_NUMS = 500; // [2013-05-29] hskang - synchronized 를 걸 필요가 없으므로 성능 향상을 위해서 뺐음. // 이 메서드 안에서는 멤버변수를 사용하지 않음. 파라미터는 Stack에 저장되므로 멀티 쓰레드라 하더라도 공유하지 않음. // public synchronized String format(String s, int initialIndent) public String format(String s, int indentNumChars, int initialIndent) { boolean singleLine = false; int indent = initialIndent; StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char currentChar = s.charAt(i); if (currentChar == '<') { char nextChar = s.charAt(i + 1); if (nextChar == '/') indent -= indentNumChars; if (!singleLine) // Don't indent before closing element if // we're creating opening and closing // elements on a single line. sb.append(buildWhitespace(indent)); if (nextChar != '?' && nextChar != '!' && nextChar != '/') indent += indentNumChars; singleLine = false; // Reset flag. } sb.append(currentChar); if (currentChar == '>') { if (s.charAt(i - 1) == '/') { indent -= indentNumChars; } int nextStartElementPos = s.indexOf('<', i); if (nextStartElementPos > i + 1) { String textBetweenElements = s.substring(i + 1, nextStartElementPos); if( textBetweenElements.trim().length() == 0 ) { textBetweenElements = "\n"; sb.append(textBetweenElements); } else { if( textBetweenElements.length() > SINGLE_LINE_CHAR_NUMS ) { sb.append("\n" + buildWhitespace(indent) + textBetweenElements + "\n"); } else { sb.append(textBetweenElements); singleLine = true; } } i = nextStartElementPos - 1; } else if( nextStartElementPos == i + 1 ) { sb.append("\n"); } } } return sb.toString(); } } private static StringBuilder buildWhitespace(int numChars) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < numChars; i++) sb.append(" "); return sb; } public static void main(String[] args) { StringBuilder sample1 = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); sample1.append("<SyncML xmlns=\"SYNCML:SYNCML1.2\">\n"); sample1.append(" <SyncHdr>\n"); sample1.append(" <VerDTD>12345678901234567890123456789012345678901</VerDTD>\n"); sample1.append(" </SyncHdr>\n"); sample1.append("<Final/>\n"); sample1.append("</SyncML>\n"); StringBuilder sample2 = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); sample2.append("<SyncML xmlns=\"SYNCML:SYNCML1.2\">"); sample2.append("<SyncHdr>"); sample2.append("<VerDTD>1.2</VerDTD>"); sample2.append("</SyncHdr>"); sample2.append("<Final/>"); sample2.append("</SyncML>"); StringBuilder sample3 = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); sample3.append("<SyncML xmlns=\"SYNCML:SYNCML1.2\">\n"); sample3.append("<SyncHdr>\n"); sample3.append("<VerDTD>1.2</VerDTD>\n"); sample3.append("</SyncHdr>\n"); sample3.append("<Final/>\n"); sample3.append("</SyncML>\n"); String formatXml = XmlUtils.formatXml(sample1.toString()); System.out.println(formatXml); System.out.println("#########################"); } }
'Java' 카테고리의 다른 글
Maven에서 의존 라이브러리들 같이 패키징 하기 (0) | 2013.06.13 |
---|---|
Best Useful Eclipse Plugins (0) | 2013.06.13 |
STS 에서 myBatis mapper xml 저장할때 느려짐 (1) | 2013.05.15 |
process map 관련 오픈소스 (0) | 2013.04.19 |
[eclipse plugin] OMA DM Simulator (0) | 2013.03.30 |