Java: Transformer Tarafından Oluşturulan XML Nasıl Girintilenir


112

Bir DOM belgesi almak ve elde edilen XML'i yazdırmak için Java'nın yerleşik XML dönüştürücüsünü kullanıyorum. Sorun, "girinti" parametresini açıkça ayarlamasına rağmen metnin hiç girintilememesidir.

basit kod

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

 }
}

sonuç

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

İstenen sonuç

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

Düşünceler?

Yanıtlar:


215

'INDENT'i etkinleştirmeniz ve transformatör için girinti miktarını ayarlamanız gerekir:

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

Güncelleme:


Referans: Serileştirmeden önce bir DOM'dan yalnızca boşluklu metin düğümleri nasıl çıkarılır?

(Tüm üyelere özellikle @ marc-novakowski, @ james-murty ve @saad'a çok teşekkürler) :


70
Varsayılan girintinin 0 olması bana aptalca geliyor, ancak buna ek olarak INDENT=yesşunu da eklemem gerekiyor:t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
lapo

1
Dikkat. Bu girinti özelliği java 5'te çalışmıyor. Java 7'de çalışıyor. Java 6'da denemedim
Hilikus

4
Birden çok çizgi olan iç düğümler varsa, iç kısmı da girintileyebilir misiniz? Sadece bunu kullanmak iç düğümlerin girintisini artırmaz.
eipark

1
@eipark with stackoverflow.com/a/979606/837530 , boşlukları kaldırdım ve şimdi bir cazibe gibi girintiler
Sa'ad

1
@lapo eğer sağlayıcınız xalan ise (ki bu çalışıyorsa muhtemelen öyledir), o zaman şu org.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT
adla

21

Önerilen çözümlerin hiçbiri benim için işe yaramadı. Bu yüzden, daha önce bahsedilen ikisinin ve üçüncü bir adımın karışımı olan alternatif bir çözüm aramaya devam ettim.

  1. girinti numarasını trafo fabrikasına ayarlayın
  2. transformatördeki girintiyi etkinleştirin
  3. otuputstream'i bir yazarla (veya arabelleğe alan yazarla) sarın
//(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 işleme kodunun "hatalı" davranışını geçici olarak çözmek için (3) yapmanız gerekir.

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

(Kaynağımı yanlış gösterdiysem lütfen bana bildirin)


3
Son satırdaki "out" neyi kastediyor?
mujimu

Bir yapıcı kullanarak yeni bir tam sayı oluşturmanız gerekiyor mu?
Benjineer

Sanırım sağlayıcınız Xalan değil. TransformerFactoryBaşkalarının bilmesi için gerçekte ne olduğunu kontrol edebilir misin ?
OrangeDog

Adım 3, a'yı Writerçıktı olarak kullanmak önemlidir.
erickson

14

Aşağıdaki kod Java 7 ile benim için çalışıyor. Çalışması için transformatördeki (transformatör fabrikası değil) girinti (evet) ve girinti miktarını (2) ayarladım.

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'ın özniteliği ayarlama çözümü benim için işe yaramadı, ancak @ lapo'nun yorumu faydalı oldu.


8

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

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

Bu dahili bir sınıftır, bu nedenle kodunuz diğer (veya daha yeni) JVM'lere taşınabilir olmayacaktır.
OrangeDog

5

Girintiyi istiyorsanız, bunu TransformerFactory.

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

4

Transformer ile uğraşmak yerine Xerces (Apache) kütüphanesini kullandım. Kitaplığı ekledikten sonra aşağıdaki kodu ekleyin.

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

Evet. Diğer tüm yaklaşımları Transformer ile denedim ama hepsi bozuk. Tüm W3C kitaplığı bir karmaşa. Xerces çalıştı.
2017

3

Benim için DOCTYPE_PUBLICişe yaradı:

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, "evet"); anahtar
silentsudo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.