从javax.xml.transform.Transformer的漂亮打印输出只有标准的Java API(缩进和Doctype定位)

使用以下简单的代码:

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

我得到的输出:

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

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

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

我猜你必须设置用于缩进的空格的数量,因为许多与外部库的答案,但我只是无法find在哪里指定,在Java API。 鉴于在java api中存在将缩进属性设置为“是”的可能性,必须以某种方式执行缩进。 我只是不知道如何。

缺less的部分是缩进量。 您可以按如下方式设置缩进和缩进量:

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

一个小工具类作为例子…

 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由xeresImpl提供。 这是maven的依赖:

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

你可以在这里find你最喜欢的构build工具的依赖: http : //mvnrepository.com/artifact/xerces/xercesImpl/2.11.0 。

您可能可以使用XSLT文件来优化所有内容。 谷歌抛出了一些结果,但我不能评论他们的正确性。

要使输出成为有效的XML文档, 有效的XML文档必须以处理指令开始。 有关更多详细信息,请参阅XML规范http://www.w3.org/TR/REC-xml/#sec-prolog-dtd