Java: jak wciąć XML wygenerowany przez Transformer

Używam wbudowanego w Javę transformatora XML, aby pobrać dokument DOM i wydrukować wynikowy XML. Problem polega na tym, że w ogóle nie wcina tekstu, pomimo jawnego ustawienia parametru "indent".

Przykładowy 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()));

 }
}

Wynik

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

Pożądany rezultat

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<a>
 <b/>
</a>
Myśli?
Author: Mike, 2009-09-06

7 answers

Musisz włączyć 'INDENT' i ustawić ilość wcięcia dla transformatora:

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

Aktualizacja:


Reference: Jak usunąć węzły tekstowe z drzewa DOM przed serializacją?

(Wielkie podziękowania dla wszystkich członków, zwłaszcza @ marc-novakowski, @ james-murty i @saad):

 198
Author: adatapost,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:09:57

Żadne z proponowanych rozwiązań nie zadziałało dla mnie. Szukałam więc alternatywnego rozwiązania, które skończyło się na połączeniu dwóch wyżej wymienionych i trzeciego kroku.

  1. Ustaw numer indent do transformerfactory
  2. Włącz Wcięcie w transformatorze
  3. W tym celu należy użyć funkcji buforedwriter (lub buforedwriter).]}
//(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"));

Musisz zrobić (3), aby obejść "buggy" zachowanie kod obsługi xml.

Źródło: johnnymac75 @ http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446

(jeśli błędnie podałem Źródło, proszę dać mi znać)

 19
Author: mabac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-03 23:52:07

Poniższy kod działa dla mnie z Javą 7. Ustawiłem indent (yes) I indent-amount (2) na transformatorze (Nie w fabryce transformatorów), aby to działało.

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

Rozwiązanie @ mabac do Ustawienia atrybutu nie zadziałało dla mnie, ale komentarz @ lapo okazał się pomocny.

 14
Author: remipod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-04 17:57:30

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

transformer.setOutputProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "2");
 8
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-06 14:41:59

Jeśli chcesz mieć wcięcia, musisz podać je do TransformerFactory.

TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", new Integer(2));
Transformer t = tf.newTransformer();
 4
Author: lucbelanger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-04 21:39:00

Użyłem Biblioteki Xerces (Apache) zamiast mieszać z Transformerem. Po dodaniu biblioteki dodaj poniższy kod.

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);
 4
Author: sevensevens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-06 18:56:29

Dla mnie dodanie DOCTYPE_PUBLIC zadziałało:

transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "10");
 2
Author: Vikas Chowdhury,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-12 12:31:58