来自javax.xml.transform.Transformer的漂亮打印输出,只有标准的java api(缩进和Doctype定位)

Ald*_*ath 55 java xml pretty-print

使用以下简单代码:

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

}
Run Code Online (Sandbox Code Playgroud)

我得到输出:

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

<aaa>
<bbb/>
<ccc/>
</aaa>
Run Code Online (Sandbox Code Playgroud)

问题A:doctype标签出现在文档注释之后.是否有可能在文件评论之前出现?

问题B:如何仅使用JavaSE 5.0 API实现缩进?这个问题基本上与如何从java中打印xml相同,该问题中的几乎所有答案都依赖于外部库.唯一适用的答案(由名为Lorenzo Boccaccia的用户发布)仅使用java的api,基本上等于上面发布的代码,但对我不起作用(如输出中所示,我没有缩进).

我猜你必须设置用于缩进的空格量,因为许多外部库的答案都有,但我找不到在java api中指定的位置.鉴于在java api中存在将缩进属性设置为"是"的可能性,必须能够以某种方式执行缩进.我只是无法弄清楚如何.

Ric*_*ler 112

缺少的部分是缩进量.您可以设置缩进和缩进量,如下所示:

transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(xmlInput, xmlOutput);
Run Code Online (Sandbox Code Playgroud)

  • 我对api的看法似乎告诉我api应该由执行指定任务的函数/方法组成,并且在使用api时,不需要直接对底层实现进行处理.但话说回来,我只是一个新手程序员,也许事情只会像我认为他们应该在乌托邦世界中那样运作.我仍然认为OutputKeys.INDENT存在于api级别的事实应该意味着api级别的缩进是可能的,除非api有缺陷(或者Apache的实现有缺陷,不能解释属性) (5认同)
  • 这是我一直这样做的方式,但在这里它不起作用,可能是一个不同的XML库.我做了`factory.setAttribute("indent-number",4);`现在它可以了. (5认同)
  • 正如你所说,它取决于Xalan,但这是jdk的一部分.据我所知,没有API级别设置来设置缩进,所以如果用户使用不同的实现,你需要添加切换处理以设置该实现的缩进.但是你不是在控制所使用的实现吗? (2认同)

小智 5

一个小的util类作为示例...

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);
}
}
Run Code Online (Sandbox Code Playgroud)

XMLserializer由Apache Foundation的 xercesImpl提供。这是Maven依赖项:

<dependency>
    <groupId>xerces</groupId>
    <artifactId>xercesImpl</artifactId>
    <version>2.11.0</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到最喜欢的构建工具的依赖项:http : //mvnrepository.com/artifact/xerces/xercesImpl/2.11.0