2010-09-07 144 views
4

要温和。PrettyPrinting。忽略空白

我试图使用javax.xml.transform.Transformer来格式化一些xml字符串,以便在标签之间缩进/无空格。如果标签之间没有空格,它就可以正常工作。如果有这种行为很奇怪。我会举一个例子。我试图跟进以下主题:http://forums.sun.com/thread.jspa?messageID=2054303#2699961。没有成功。

代码遵循:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    factory.setIgnoringElementContentWhitespace(true); 
    DocumentBuilder builder = factory.newDocumentBuilder(); 
    DOMImplementation domImpl = builder.getDOMImplementation(); 
    DOMImplementationLS ls = (DOMImplementationLS) domImpl.getFeature("LS", "3.0"); 
    LSInput in = ls.createLSInput(); 
    in.setByteStream(new ByteArrayInputStream(input.getBytes())); 
    LSParser parser = ls.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, 
    "http://www.w3.org/2001/XMLSchema"); 
    Document xmlInput = parser.parse(in); 

    StringWriter stringWriter = new StringWriter(); 
    StreamResult xmlOutput = new StreamResult(stringWriter); 
    TransformerFactory f = TransformerFactory.newInstance(); 
    f.setAttribute("indent-number", 2); 

    Transformer transformer = f.newTransformer(); 
    transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
    transformer.setOutputProperty(OutputKeys.METHOD, "xml"); 
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 
    transformer.transform(new DOMSource(xmlInput), xmlOutput); 

如果有标签

input : <tag><nested> hello </nested></tag> 
output : 
<tag> 
    <nested> hello </nested> 
</tag> 

之间没有中断,如果有:

input : <tag> <nested> hello </nested></tag> 
output : 
<tag> <nested> hello </nested> 
</tag> 

JVM 1.6。

这里有什么明显的错误?

回答

3

这必须是变压器实施的问题。我创建了一个小的测试类,它读取一个没有空格或换行符的字符串作为XML,并从XSLT样式表(也来自字符串)创建一个转换器。样式表指定必须发生缩进。这是基本实现你用transformer.setOutputProperty(OutputKeys.INDENT, "yes");

这是什么做的另一种方式:

package transformation; 

import java.io.StringReader; 

import javax.xml.transform.Result; 
import javax.xml.transform.Source; 
import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.transform.stream.StreamSource; 

public class TransformerTest { 

    public static void main(String[] args) throws Exception { 

     final String xmlSample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><tag><nested>hello</nested></tag>"; 
     final String stylesheet = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"><xsl:output method=\"xml\" version=\"1.0\" indent=\"yes\"/><xsl:template match=\"node()|@*\"><xsl:copy><xsl:apply-templates select=\"node()|@*\"/></xsl:copy></xsl:template></xsl:stylesheet>"; 

     final TransformerFactory factory = TransformerFactory.newInstance(); 

     final Source xslSource = new StreamSource(new StringReader(stylesheet)); 
     final Transformer transformer = factory.newTransformer(xslSource); 

     final Source source = new StreamSource(new StringReader(xmlSample)); 
     final Result result = new StreamResult(System.out); 

     transformer.transform(source, result); 

    } 

} 

现在奇怪的是,结果各不相同基础上我用的变压器。如果我不把在类路径中(使用默认实现在JRE库)任何的TransformerFactory实现,结果是这样的:

<?xml version="1.0" encoding="UTF-8"?> 
<tag> 
<nested>hello</nested> 
</tag> 

不正确的,因为标签是不缩进。

然后,通过在classpath中加入了最近实施的Xalan(xalan.jar和serializer.jar,仍然使用JRE默认解析器/ DOM建设者),我得到这个:

<?xml version="1.0" encoding="UTF-8"?><tag> 
<nested>hello</nested> 
</tag> 

还是不正确,第一个标签和XML声明在同一行,并且没有缩进。

说实话,这让我很震惊。我会理解标签之间或文本节点周围的空白是否会影响缩进,因为变压器可能会假设其中一些是不可忽略的。但是看到这样一个简单的XML就像这样变得很奇怪。我想也许使用控制台输出可能与它有关,所以我试图将流式传输到一个文件。同样的结果。

有点奇怪多久的变压器实现仍然有这样的行为。但是,当我注意到使用Schema的Validator导致属性从“增强”XML输出中删除时,这种情况几乎没有那么糟糕。

因此,除了尝试寻找其他处理器并查看是否存在同样的问题之外,似乎没有多少工作要做。也许撒克逊值得一试。这个错误报告也很有趣(它适用于Java 1。5,不过): http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446

+0

该属性解决了我的问题!谢谢! +1 – 2013-05-21 16:00:31

0

变压器似乎不喜欢白色的空间,所以最简单的解决方案似乎是简单地 删除....

public String prettyPrintXML(String inXML) { 

     String outXML = inXML; 

// The transformer doesn't like white space between tags so remove it.   
      String[] bits = inXML.split(">");  
     inXML=""; 
     boolean first = true; 
     for (int n=0;n<bits.length; n++){ 
      if (first) 
      inXML = inXML + bits[n].trim(); 
      else 
      inXML = inXML + ">"+bits[n].trim(); 

      first = false; 
     } 
     inXML = inXML + ">"; 

传递inXML成你的变压器和你走了。

+0

不是。试过了。变压器是简单的破碎。 – Tuntable 2017-11-10 07:38:35