web-dev-qa-db-de.com

Hübsche Druckausgabe von javax.xml.transform.Transformer mit nur Java-Standard-API (Indentation und Doctype-Positionierung)

Verwenden Sie den folgenden einfachen Code:

package test;

import Java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class TestOutputKeys {
    public static void main(String[] args) throws TransformerException {

        // Instantiate transformer input
        Source xmlInput = new StreamSource(new StringReader(
                "<!-- Document comment --><aaa><bbb/><ccc/></aaa>"));
        StreamResult xmlOutput = new StreamResult(new StringWriter());

        // Configure transformer
        Transformer transformer = TransformerFactory.newInstance()
                .newTransformer(); // An identity transformer
        transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "testing.dtd");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.transform(xmlInput, xmlOutput);

        System.out.println(xmlOutput.getWriter().toString());
    }

}

Ich bekomme die Ausgabe:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Document comment --><!DOCTYPE aaa SYSTEM "testing.dtd">

<aaa>
<bbb/>
<ccc/>
</aaa>

Frage A: Das Doctype-Tag wird nach dem Dokumentkommentar angezeigt. Ist es möglich, es vor dem Dokumentkommentar erscheinen zu lassen?

Frage B: Wie erreiche ich Einrückungen nur mit der JavaSE 5.0-API? Diese Frage ist im Wesentlichen identisch mit Wie man XML aus Java hübsch druckt , jedoch Fast alle Antworten in dieser Frage hängen von externen Bibliotheken ab. Die einzig zutreffende Antwort (gepostet von einem Benutzer namens Lorenzo Boccaccia), der nur Javas API verwendet, entspricht im Grunde dem oben geposteten Code, funktioniert aber nicht für mich (wie in der Ausgabe gezeigt, bekomme ich keine Einrückung).

Ich vermute, dass Sie die Anzahl der Leerzeichen festlegen müssen, die für Einrückungen verwendet werden sollen, wie dies bei vielen Antworten mit externen Bibliotheken der Fall ist, aber ich kann nur nicht herausfinden, wo dies in der Java-API angegeben werden soll. Da es in der Java-API die Möglichkeit gibt, eine Einrückungseigenschaft auf "yes" zu setzen, muss es möglich sein, die Einrückung irgendwie auszuführen. Ich kann nur nicht herausfinden, wie.

55
Alderath

Der fehlende Teil ist die Einrückung. Sie können den Einzug und den Einzugsbetrag wie folgt einstellen:

transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.Apache.org/xslt}indent-amount", "2");
transformer.transform(xmlInput, xmlOutput);
112
Rich Seller

Eine kleine Nutzungsklasse als Beispiel ...

import org.Apache.xml.serialize.XMLSerializer;

public class XmlUtil {

public static Document file2Document(File file) throws Exception {
    if (file == null || !file.exists()) {
        throw new IllegalArgumentException("File must exist![" + file == null ? "NULL"
                : ("Could not be found: " + file.getAbsolutePath()) + "]");
    }
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    dbFactory.setNamespaceAware(true);
    return dbFactory.newDocumentBuilder().parse(new FileInputStream(file));
}

public static Document string2Document(String xml) throws Exception {
    InputSource src = new InputSource(new StringReader(xml));
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    dbFactory.setNamespaceAware(true);
    return dbFactory.newDocumentBuilder().parse(src);
}

public static OutputFormat getPrettyPrintFormat() {
    OutputFormat format = new OutputFormat();
    format.setLineWidth(120);
    format.setIndenting(true);
    format.setIndent(2);
    format.setEncoding("UTF-8");
    return format;
}

public static String document2String(Document doc, OutputFormat format) throws Exception {
    StringWriter stringOut = new StringWriter();
    XMLSerializer serial = new XMLSerializer(stringOut, format);
    serial.serialize(doc);
    return stringOut.toString();
}

public static String document2String(Document doc) throws Exception {
    return XmlUtil.document2String(doc, XmlUtil.getPrettyPrintFormat());
}

public static void document2File(Document doc, File file) throws Exception {
    XmlUtil.document2String(doc, XmlUtil.getPrettyPrintFormat());
}

public static void document2File(Document doc, File file, OutputFormat format) throws Exception {
    XMLSerializer serializer = new XMLSerializer(new FileOutputStream(file), format);
    serializer.serialize(doc);
}
}

XMLserializer wird von xercesImpl von der Apache Foundation bereitgestellt. Hier ist die Mavenabhängigkeit:

<dependency>
    <groupId>xerces</groupId>
    <artifactId>xercesImpl</artifactId>
    <version>2.11.0</version>
</dependency>

Die Abhängigkeit zu Ihrem bevorzugten Build-Tool finden Sie hier: http://mvnrepository.com/artifact/xerces/xercesImpl/2.11.0 .

4
Rob

Sie könnten wahrscheinlich alles mit einer XSLT-Datei begleichen. Google wirft einige Ergebnisse auf, aber ich kann deren Korrektheit nicht kommentieren.

1
McDowell

Um die Ausgabe zu einem gültigen XML-Dokument zu machen, NEIN. Ein gültiges XML-Dokument muss mit einer Verarbeitungsanweisung beginnen. Weitere Informationen finden Sie in der XML-Spezifikation http://www.w3.org/TR/REC-xml/#sec-prolog-dtd .

0
Oskar