Java: Bagaimana Indentasi XML yang Dihasilkan oleh Transformer


112

Saya menggunakan transformator XML bawaan Java untuk mengambil dokumen DOM dan mencetak XML yang dihasilkan. Masalahnya adalah bahwa teks sama sekali tidak menjorok ke dalam meskipun telah menyetel parameter "indentasi" secara eksplisit.

Kode sampel

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()));

 }
}

hasil

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

hasil yang diinginkan

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

Pikiran?

Jawaban:


215

Anda perlu mengaktifkan 'INDENT' dan menyetel jumlah indentasi untuk transformator:

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

Memperbarui:


Referensi: Bagaimana cara menghapus node teks khusus spasi dari DOM sebelum serialisasi?

(Banyak terima kasih kepada semua anggota terutama @ marc-novakowski, @ james-murty dan @saad) :


70
Tampak konyol bagi saya bahwa lekukan default adalah 0, tetapi selain itu INDENT=yessaya juga harus menambahkan ini:t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
lapo

1
Awas. Properti indentasi ini tidak berfungsi di java 5. ia berfungsi di java 7. Belum mencoba di java 6
Hilikus

4
Jika ada node dalam yang terdiri dari beberapa baris, dapatkah Anda membuat indentasi bagian dalamnya juga? Hanya menggunakan ini tidak mengindentasi node bagian dalam.
eipark

1
@eipark dengan stackoverflow.com/a/979606/837530 , saya menghapus spasi, dan sekarang indentasi seperti pesona
Sa'ad

1
@lapo jika penyedia Anda adalah xalan (yang mungkin jika ini berfungsi), maka tersedia sebagaiorg.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT
OrangeDog

21

Tak satu pun dari solusi yang disarankan berhasil untuk saya. Jadi saya terus mencari solusi alternatif, yang akhirnya menjadi campuran dari dua langkah sebelumnya dan langkah ketiga.

  1. atur nomor indentasi ke dalam pabrik transformator
  2. aktifkan indentasi pada transformator
  3. membungkus otuputstream dengan penulis (atau penulis buffered)
//(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"));

Anda harus melakukan (3) untuk mengatasi perilaku "buggy" dari kode penanganan xml.

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

(Jika saya salah mengutip sumber saya, beri tahu saya)


3
Apa yang dimaksud dengan "keluar" di baris terakhir?
mujimu

Apakah Anda perlu membuat integer baru menggunakan konstruktor?
Benjineer

Saya menebak karena penyedia Anda bukan Xalan. Bisakah Anda memeriksa apa Anda TransformerFactorysebenarnya sehingga orang lain tahu.
OrangeDog

Langkah 3, menggunakan a Writersebagai output, sangat penting.
erickson

14

Kode berikut berfungsi untuk saya dengan Java 7. Saya mengatur indentasi (ya) dan jumlah indentasi (2) pada trafo (bukan pabrik trafo) untuk membuatnya berfungsi.

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);

Solusi @ mabac untuk menyetel atribut tidak berhasil untuk saya, tetapi komentar @ lapo terbukti membantu.


8

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

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

Ini adalah kelas internal, jadi kode Anda tidak akan portabel ke JVM lain (atau bahkan yang lebih baru).
OrangeDog

5

Jika Anda menginginkan indentasi, Anda harus menentukannya ke TransformerFactory.

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

4

Saya menggunakan perpustakaan Xerces (Apache) daripada mengotak-atik Transformer. Setelah Anda menambahkan perpustakaan, tambahkan kode di bawah ini.

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);

Iya. Saya mencoba semua pendekatan lain dengan Transformer tetapi semuanya rusak. Seluruh perpustakaan W3C berantakan. Xerces bekerja.
Tuntable

3

Bagi saya menambahkan DOCTYPE_PUBLICberhasil:

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"); adalah kuncinya
silentsudo
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.