2009-08-12 24 views
53

Sử dụng mã đơn giản sau đây:Khá-in đầu ra từ javax.xml.transform.Transformer với api chỉ tiêu chuẩn java (Indentation và định vị 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()); 
    } 

} 

tôi nhận được kết quả:

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

<aaa> 
<bbb/> 
<ccc/> 
</aaa> 

Câu hỏi A: Thẻ doctype xuất hiện sau khi nhận xét tài liệu. Có thể làm cho nó xuất hiện trước khi nhận xét tài liệu?

Câu hỏi B: Làm cách nào để đạt được thụt đầu dòng, chỉ sử dụng API JavaSE 5.0? Câu hỏi này về cơ bản giống hệt với How to pretty-print xml from java, tuy nhiên hầu như tất cả các câu trả lời trong câu hỏi đó đều phụ thuộc vào thư viện bên ngoài. Câu trả lời áp dụng duy nhất (được đăng bởi một người dùng tên Lorenzo Boccaccia) chỉ sử dụng api của java, về cơ bản là bằng mã được đăng ở trên, nhưng không hoạt động đối với tôi (như được hiển thị trong đầu ra, tôi không nhận được thụt đầu dòng).

Tôi đoán rằng bạn phải đặt số lượng khoảng trống để sử dụng cho thụt lề, vì nhiều câu trả lời có thư viện bên ngoài, nhưng tôi không thể tìm thấy nơi để chỉ định trong java api. Với thực tế là khả năng để thiết lập một tài sản thụt đầu dòng để "có" tồn tại trong api java, nó phải có thể thực hiện thụt đầu dòng bằng cách nào đó. Tôi không thể hiểu được làm thế nào.

+0

Câu hỏi A không có ý nghĩa. Bạn có nghĩa là "trước" trong phần thứ hai? –

+0

Có. Tôi đã chỉnh sửa câu hỏi để thay đổi lỗi đánh máy. Cảm ơn bạn. – Alderath

+4

Lặp lại nhận xét tôi đã tạo trong http://stackoverflow.com/questions/139076/how-to-pretty-print-xml-from-java - bây giờ bạn có thể in đẹp mà không cần thư viện bên ngoài. Xem http://xerces.apache.org/xerces2-j/faq-general.html#faq-6. Có đây là một câu hỏi thường gặp của Xerces nhưng câu trả lời bao gồm các lớp JDK tiêu chuẩn. Việc triển khai 1.5 ban đầu của các lớp này có nhiều vấn đề nhưng mọi thứ hoạt động tốt từ 1.6 trở lên. Sao chép ví dụ LSSerializer trong FAQ, cắt bit "..." và thêm 'writer.getDomConfig(). SetParameter (" format-pretty-print ", Boolean.TRUE);' sau khi 'LSSerializer writer = ... 'dòng. –

Trả lời

106

Phần còn thiếu là số tiền thụt lề. Bạn có thể đặt thụt lề và thụt lề số tiền như sau:

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

hmm chỉ cần thử nghiệm này với mẫu của bạn và có một lỗi –

+0

nó hoạt động cho tôi – dfa

+0

tốt để biết, tôi nghĩ rằng nó không thành công vì tôi đã có một phiên bản cũ của xalan, kiểm tra đôi –

1

Có thể bạn có thể làm hài lòng mọi thứ với XSLT file. Google đưa ra một vài kết quả, nhưng tôi không thể bình luận về tính chính xác của chúng.

+0

Tôi thích ý tưởng này. Tôi sử dụng XSLT một chút công bằng cho loại điều này (không gian tên maniuplation, kiểm soát khoảng trắng, vv). Nó không hiệu quả, nhưng nó khá dễ dàng và không phụ thuộc vào trình phân tích cú pháp. – skaffman

4

Một chút lớp util là một ví dụ ...

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 được cung cấp bởi xeresImpl. Đây là phụ thuộc maven:

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

Bạn có thể tìm sự phụ thuộc cho công cụ xây dựng yêu thích của mình tại đây: http://mvnrepository.com/artifact/xerces/xercesImpl/2.11.0.

+0

Thêm tài liệu tham khảo vào thư viện bên ngoài. Mẫu này không chỉ hoạt động với JDK. XMLSerializer thuộc về org.apache.xml.serialize. – Aubin

0

Để làm cho đầu ra thành một tài liệu XML hợp lệ, KHÔNG. Một tài liệu XML hợp lệ phải bắt đầu bằng một lệnh xử lý. Xem đặc tả XML http://www.w3.org/TR/REC-xml/#sec-prolog-dtd để biết thêm chi tiết.

+0

Câu trả lời này dựa trên sự hiểu lầm của câu hỏi. Nhận xét được phép là trước hoặc sau khai báo loại tài liệu. I E. bạn có thể có 'xmlDeclaration comment doctypeDeclaration' hoặc' xmlDeclaration doctypeDeclaration comment'. Các câu hỏi không bao giờ nói về việc đưa bất cứ điều gì trước khi xmlDeclaration. – Alderath

+0

Vâng, bạn nói đúng. Ngu ngốc tôi ... – Oskar

Các vấn đề liên quan