125 Stimmen

Java: Einrücken von durch Transformer erzeugtem XML

Ich verwende den in Java eingebauten XML-Transformer, um ein DOM-Dokument zu nehmen und das resultierende XML auszudrucken. Das Problem ist, dass der Text überhaupt nicht eingerückt wird, obwohl ich den Parameter "indent" explizit gesetzt habe.

Beispielcode

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

 }
}

Ergebnis

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

gewünschtes Ergebnis

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

Was denken Sie?

236voto

KV Prajapati Punkte 91877

Sie müssen "INDENT" aktivieren und den Einrückungsbetrag für den Transformator festlegen:

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

Aktualisierung:


Hinweis : Wie zu entfernen Whitespace-only Text-Knoten aus einem DOM vor der Serialisierung?

(Vielen Dank an alle Mitglieder, insbesondere an @marc-novakowski, @james-murty und @saad) :

72 Stimmen

Es scheint mir dumm, dass die Standardeinrückung 0 ist, aber zusätzlich zu INDENT=yes Ich musste auch dies hinzufügen: t.setOutputProperty("{http://xml.apache.org/xslt}indent-amou‌​nt", "2");

1 Stimmen

Vorsicht! Diese Einrückungseigenschaft funktioniert nicht in Java 5. In Java 7 funktioniert sie. Ich habe es nicht in Java 6 versucht.

4 Stimmen

Wenn es innere Knoten gibt, die aus mehreren Zeilen bestehen, können Sie dann auch den inneren Teil einrücken? Wenn Sie dies verwenden, werden die inneren Knoten nicht eingerückt.

24voto

mabac Punkte 1350

Keine der vorgeschlagenen Lösungen hat bei mir funktioniert. Also suchte ich weiter nach einer alternativen Lösung, die schließlich eine Mischung aus den beiden zuvor genannten und einem dritten Schritt war.

  1. Setzen der Spiegelstrichnummer in die Transformatorfabrik
  2. den Einzug im Transformator aktivieren
  3. den Otuputstream mit einem Writer (oder Bufferedwriter) umhüllen

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

Sie müssen (3) tun, um ein "fehlerhaftes" Verhalten des xml-Verarbeitungscodes zu umgehen.

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

(Sollte ich meine Quelle falsch zitiert haben, bitte ich um einen Hinweis)

0 Stimmen

Ich vermute, weil Ihr Anbieter nicht Xalan ist. Können Sie überprüfen, was Ihr TransformerFactory tatsächlich ist, damit andere es wissen.

0 Stimmen

Schritt 3, unter Verwendung eines Writer als Ausgabe, ist wesentlich.

14voto

remipod Punkte 10601

Der folgende Code funktioniert bei mir mit Java 7. Ich habe den Einzug (ja) und den Einzugsbetrag (2) im Transformator (nicht in der Transformator-Fabrik) eingestellt, damit es funktioniert.

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

Die Lösung von @mabac, das Attribut zu setzen, hat bei mir nicht funktioniert, aber der Kommentar von @lapo war hilfreich.

8voto

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

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

0 Stimmen

Dies ist eine interne Klasse, so dass Ihr Code nicht auf andere (oder sogar neuere) JVMs portiert werden kann.

6voto

lucbelanger Punkte 342

Wenn Sie die Einrückung wünschen, müssen Sie sie in der TransformerFactory .

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X