2010-09-07 194 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