2011-08-04 34 views
2

Java API를 사용하여 XML 문자열을 꽤 인쇄 할 수 있어야하며 웹 및이 특정 웹 사이트에서 여러 가지 해결책을 찾았습니다. . 그러나 이것을 javax.xml.transform.Transformer와 함께 작동시키려는 시도가 여러 번 있었음에도 불구하고 지금까지는 실패했습니다. 아래에 제공된 코드는 인수의 xml 문자열에 xml 요소 사이에 개행 문자가 포함되지 않은 경우에만 부분적으로 만 작동합니다. 이것은 방금 할 것입니다. 나는 꽤 잘 인쇄 된 문자열이라 할지라도, 그것이 잘 형성되고 유효한 xml이라고 가정 할 때, 무엇인가를 예쁜 것으로 인쇄 할 수 있어야합니다.Java 1.6 : javax.xml.transform.Transformer가 개행을 포함하는 XML 문자열 들여 쓰기를 거부합니다.

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

public class XMLFormatter { 

    public static String format(String xml, int indent, boolean omitXmlDeclaration) 
      throws TransformerException { 

     if (indent < 0) { 
      throw new IllegalArgumentException(); 
     } 
     String ret = null; 
     StringReader reader = new StringReader(xml); 
     StringWriter writer = new StringWriter(); 
     try { 
      TransformerFactory factory = TransformerFactory.newInstance(); 
      factory.setAttribute("indent-number", new Integer(indent)); 
      Transformer transformer = factory.newTransformer(); 
      if (omitXmlDeclaration) { 
       transformer.setOutputProperty(
         OutputKeys.OMIT_XML_DECLARATION, "yes"); 
      } 
      transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
      transformer.setOutputProperty(
        "{http://xml.apache.org/xslt}indent-amount", 
        String.valueOf(indent)); 
      transformer.setOutputProperty(OutputKeys.METHOD, "xml"); 
      transformer.transform(
        new StreamSource(reader), 
        new StreamResult(writer)); 
      ret = writer.toString(); 
     } catch (TransformerException ex) { 
      throw ex; 
     } finally { 
      if (reader != null) { 
       reader.close(); 
      } 
      try { 
       if (writer != null) { 
        writer.close(); 
       } 
      } catch (IOException ex) {} 
     } 

     return ret; 
    } 

    public static void main(String[] args) throws TransformerException { 
     StringBuilder sb = new StringBuilder(); 
     sb.append("<rpc-reply><data><smth/></data></rpc-reply>"); 

     System.out.println(sb.toString()); 
     System.out.println(); 
     System.out.println(XMLFormatter.format(sb.toString(), 4, false)); 

     final String NEWLINE = System.getProperty("line.separator"); 
     sb.setLength(0); 
     sb.append("<rpc-reply>");sb.append(NEWLINE); 
     sb.append("<data>");sb.append(NEWLINE); 
     sb.append("<smth/>");sb.append(NEWLINE); 
     sb.append("</data>");sb.append(NEWLINE); 
     sb.append("</rpc-reply>"); 

     System.out.println(sb.toString()); 
     System.out.println(); 
     System.out.println(XMLFormatter.format(sb.toString(), 4, false)); 
    } 
} 

이 코드는 그 줄 바꿈하여해야 방해해서는 안 :

나는 (사람들이 그들을 위해 일을 주장, 내가 찾은 코드 조각에서 조립)이있어? 이 버그입니까? 아니면 여기서 중요한 것을 놓치고 있습니까? 코드 조각의 출력 :

<rpc-reply><data><smth/></data></rpc-reply> 

<?xml version="1.0" encoding="UTF-8"?> 
<rpc-reply> 
    <data> 
     <smth/> 
    </data> 
</rpc-reply> 

<rpc-reply> 
<data> 
<smth/> 
</data> 
</rpc-reply> 

<?xml version="1.0" encoding="UTF-8"?> 
<rpc-reply> 
<data> 
<smth/> 
</data> 
</rpc-reply> 

는 지금까지 내가 내 코드를 말할 수있는 나만 방법 (아웃) 변환을위한 StringWriter 클래스와 StringReader를를 사용하는 다른 예와 다르다. 나는 이미 xml을 ByteArrayOutputStream으로 변환하려고 시도했으며 심지어 DOM으로 파싱 한 다음 변환 자에게 공급하지만 결과는 동일합니다. 이것이 단 일행에서만 작동하는 이유를 알고 싶습니다.

Netbeans 6.9.1과 결합 된 jdk1.6_u24를 사용하고 있습니다.

이 질문은 (그리고 아마도 다른 사람의 군중에)하지만 관련이 동일하지로 :이는 결론을 내렸다했습니다

How to pretty print XML from Java?

indent XML text with Transformer

Indent XML made with Transformer

답변

1

Transformer의 정상적인 동작. 더 나아가. 들여 쓰기 기능은 예쁜 프린터로 사용되는 것이 아니라 자체 프린터 용도로 사용됩니다. XML이 꽤 인쇄되면 XSD, DTD 또는 비슷한 것을 기반으로 문서가 어떻게 보이는지 정확히 알지 않는 한 구조가 변경됩니다. 이는 개행 문자가 무시할 수있는 공백으로 간주되고 실제 요소 값이거나 그 일부 일 수있는 유일한 줄 바꿈 문자를 결정하는 유일한 방법입니다. Transformer는 기존 공백을 다시 포맷하지 않으므로 내 코드의 출력이 그 것이다.

Transformer 또는 다른 클래스를 사용하여 이미 인쇄 된 XML 문자열을 멋지게 인쇄하려면 먼저 무시할 수있는 공백을 없애야하며 안전하게 수행 할 수있는 유일한 방법은 XML의 구조 문서는 같아야합니다. 나는 누군가가 나를 위해이 진술을 확인하기를 원한다. 왜냐하면 이것은 현재 나의 가정 일 뿐이다. 이 진술이 정확하다면; 제 3 자의 예쁜 프린터는 어떻게합니까? 나는 JTidy가 XSD를 요구하지 않았지만, 어쨌든 꽤 인쇄 된 것을 압니다. 모든 공백을 텍스트 XML 노드로 묶지 않는 한 공백을 무시할 수있는 공백으로 처리합니까? 무시할 수있는 공백을 확인하고 제거하는 다른 방법이 있습니까?