자바 : Transformer에서 생성 한 XML 들여 쓰기 방법


112

Java의 내장 XML 변환기를 사용하여 DOM 문서를 가져와 결과 XML을 인쇄하고 있습니다. 문제는 "indent"매개 변수를 명시 적으로 설정 했음에도 불구하고 텍스트를 전혀 들여 쓰지 않는다는 것입니다.

샘플 코드

public class TestXML {

 public static void main(String args[]) throws Exception {
  ByteArrayOutputStream s;

  Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
  Transformer t = TransformerFactory.newInstance().newTransformer();

  Element a,b;

  a = d.createElement("a");
  b = d.createElement("b");

  a.appendChild(b);

  d.appendChild(a);

  t.setParameter(OutputKeys.INDENT, "yes");

  s = new ByteArrayOutputStream();

  t.transform(new DOMSource(d),new StreamResult(s));

  System.out.println(new String(s.toByteArray()));

 }
}

결과

<?xml version="1.0" encoding="UTF-8" standalone="no"?><a><b/></a>

원하는 결과

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<a>
 <b/>
</a>

생각?

답변:


215

'INDENT'를 활성화하고 변환기의 들여 쓰기 양을 설정해야합니다.

t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");

최신 정보:


참조 : 직렬화 전에 DOM에서 공백 전용 텍스트 노드를 제거하는 방법은 무엇입니까?

(특히 @ marc-novakowski, @ james-murty 및 @saad 모든 회원에게 감사드립니다) :


70
기본 들여 쓰기가 0이라는 게 어리석은 것 같지만 INDENT=yes추가로 다음을 추가해야했습니다.t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
lapo

1
조심하세요. 이 들여 쓰기 속성이 자바 7에 자바가 않습니다 5에서 작동하지 않습니다 자바 6에 시도하지 않은
Hilikus

4
여러 줄의 내부 노드가있는 경우 내부 부분도 들여 쓰기 할 수 있습니까? 이것을 사용하는 것만으로는 내부 노드가 들여 쓰기되지 않습니다.
eipark 2013

1
와 @eipark stackoverflow.com/a/979606/837530는 , 나는 매력처럼 공백, 지금 들여 쓰기 제거
Sa'ad

1
공급자가 xalan이면 @lapo (이것이 작동하는 경우), 다음과 같이 사용할 수 있습니다.org.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT
OrangeDog

21

제안 된 솔루션 중 어느 것도 저에게 효과적이지 않았습니다. 그래서 나는 앞서 언급 한 두 가지와 세 번째 단계의 혼합이 된 대체 솔루션을 계속 찾았습니다.

  1. 트랜스포머 팩토리에 들여 쓰기 번호 설정
  2. 변압기에서 들여 쓰기 활성화
  3. otuputstream을 writer (또는 bufferedwriter)로 래핑합니다.
//(1)
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", new Integer(2));

//(2)
Transformer t = tf.newTransformer();
t.setOutputProperty(OutputKeys.INDENT, "yes");

//(3)
t.transform(new DOMSource(doc),
new StreamResult(new OutputStreamWriter(out, "utf-8"));

xml 처리 코드의 "버그"동작을 해결하려면 (3)을 수행해야합니다.

출처 : johnnymac75 @ http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446

(제 출처를 잘못 인용 한 경우 알려주세요)


3
마지막 줄에서 "out"은 무엇을 의미합니까?
mujimu

생성자를 사용하여 새 정수를 만들어야합니까?
Benjineer

귀하의 공급자가 Xalan이 아니기 때문에 추측하고 있습니다. TransformerFactory다른 사람들이 알 수 있도록 자신이 실제로 무엇인지 확인할 수 있습니까?
OrangeDog

3 단계, a Writer를 출력으로 사용하는 것은 필수적입니다.
erickson

14

다음 코드는 Java 7에서 저에게 효과적입니다. 트랜스포머 (트랜스포머 팩토리가 아님)에 들여 쓰기 (예)와 들여 쓰기 양 (2)을 설정하여 작동하도록했습니다.

TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.transform(source, result);

속성을 설정하는 @mabac의 솔루션이 저에게는 효과가 없었지만 @lapo의 의견은 도움이되었습니다.


8

import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory

transformer.setOutputProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "2");

이것은 내부 클래스이므로 코드를 다른 (또는 더 새로운) JVM으로 이식 할 수 없습니다.
OrangeDog

5

들여 쓰기를 원하면 TransformerFactory.

TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", new Integer(2));
Transformer t = tf.newTransformer();

4

Transformer를 엉망으로 만드는 대신 Xerces (Apache) 라이브러리를 사용했습니다. 라이브러리를 추가하면 아래 코드를 추가하십시오.

OutputFormat format = new OutputFormat(document);
format.setLineWidth(65);
format.setIndenting(true);
format.setIndent(2);
Writer outxml = new FileWriter(new File("out.xml"));
XMLSerializer serializer = new XMLSerializer(outxml, format);
serializer.serialize(document);

예. 나는 Transformer로 다른 모든 접근법을 시도했지만 모두 깨졌습니다. 전체 W3C 라이브러리는 엉망입니다. Xerces가 작동했습니다.
Tuntable

3

나를 DOCTYPE_PUBLIC위해 일 추가 :

transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "10");

Transformer.setOutputProperty (OutputKeys.DOCTYPE_PUBLIC, "yes"); 열쇠
silentsudo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.