2011-02-04 22 views
16

Bất kỳ ai biết về một hướng dẫn hay (hoặc có một ví dụ tốt) để viết XML bằng cách sử dụng khung SAX (hoặc một cái gì đó tương tự) và Java? Tìm kiếm đã mang lại rất ít về kết quả hữu ích. Tôi đang cố gắng xuất từ ​​ứng dụng Android và đang tìm cách tránh chi phí bộ nhớ cao nhất có thể.Tạo XML bằng SAX và Java

+0

SAX là một phân tích cú pháp, nó không tạo ra bất cứ điều gì :) – bestsss

+0

Trừ khi bạn hoàn toàn muốn sử dụng SAX (đôi khi có thể là trường hợp khi thực hiện đường ống xử lý), có thể bạn có thể yêu cầu các thuật ngữ chung hơn - nghĩa là, bạn đang cố gắng đạt được điều gì, trái ngược với "làm cách nào để sử dụng công cụ này"? – StaxMan

+2

Điều tôi thực sự tìm kiếm là tạo ra XML với ít chi phí bộ nhớ nhất có thể. Tôi đã nhìn thấy một số ví dụ bằng cách sử dụng khung SAX, nhưng không có gì cụ thể cho một newb Java như bản thân mình để tìm thấy hữu ích. – Lunchbox

Trả lời

14

Có một kỹ thuật rất hữu ích cho tạo XML trực tiếp từ các POJO qua khuôn khổ SAX (không phải là một phân tích cú pháp SAX, nhưng Khung SAX). Kỹ thuật này có thể được sử dụng để tạo một tài liệu XML.

Tạo XML từ một cấu Arbitrary liệu
http://download.oracle.com/javaee/1.4/tutorial/doc/JAXPXSLT5.html

Về cơ bản, bạn có thêm các phương pháp để POJO của bạn hoặc viết lớp tiện ích cho các POJO của bạn mà biến chúng thành bộ phát sự kiện SAX (phát ra các sự kiện như một phân tích cú pháp SAX thường khi phân tích cú pháp một tài liệu XML). Bây giờ "trình tạo sự kiện SAX" của bạn trông giống như phần đầu ra của trình phân tích cú pháp SAX và có thể được cung cấp bất kỳ trình xử lý nội dung nào mà trình phân tích SAX sẽ thực hiện, chẳng hạn như trình phân tích cú pháp in XML. Nhưng nó cũng có thể là nguồn cấp dữ liệu cho trình phân tích cú pháp DOM để tạo một cây DOM hoặc nguồn cấp dữ liệu cho một công cụ XSLT để tạo HTML hoặc thực hiện dịch XSL đúng mà không cần phải tạo một tài liệu XML trung gian từ các POJO.

Ví dụ, một lớp người có thể có một phương pháp emitXML() bao gồm những dòng này:

handler.startElement(nsu, PERSON_TAG, PERSON_TAG, NO_ATTRIBUTES); 

handler.startElement(nsu, FIRSTNAME_TAG, FIRSTNAME_TAG, atts); 
handler.characters(this.firstName.toCharArray(), 
     0, 
     this.firstName.length()); 
handler.endElement(nsu, FIRSTNAME_TAG, FIRSTNAME_TAG); 

... emit more instance variables 

... emit child object like: homeAddress.emitXML(handler, ...); 

handler.endElement(nsu, PERSON_TAG, PERSON_TAG); 

Cập nhật:

Một vài tài liệu tham khảo khác:


Một vài phản ứng với nhận xét:

Điều này đúng, nhưng giao diện XMLStreamWriter mô tả ở trên là sử dụng nhiều hơn nữa -thân thiện.- Michael Kay 3 giờ trước

Có, nhưng tôi đoán tôi không rõ ràng. Tôi có thể dễ dàng duyệt qua phân cấp và sử dụng XMLStreamWriter để trực tiếp xuất tài liệu XML sang luồng. Tuy nhiên, các bài viết cho thấy một kỹ thuật mạnh mẽ để đi qua hệ thống phân cấp và tạo các sự kiện SAX, thay vì xuất trực tiếp một tài liệu XML. Bây giờ tôi có thể cắm các trình xử lý nội dung khác nhau để thực hiện các việc khác nhau hoặc tạo ra các phiên bản XML khác nhau. Chúng tôi cũng có thể cung cấp phân cấp đối tượng cho bất kỳ công cụ nào đã chấp nhận trình phân tích cú pháp SAX, như một công cụ XSLT. Nó thực sự chỉ tận dụng mẫu khách truy cập được thiết lập bởi khung công tác SAX: chúng ta tách riêng việc duyệt qua phân cấp từ đầu ra XML. Các phần xuất XML, trình xử lý nội dung, chắc chắn nên sử dụng một XMLStreamWriter nếu mục đích của chúng là viết một luồng XML. Ví dụ, trên chương trình của chúng tôi, chúng tôi đã gửi tin nhắn XML qua các ổ cắm mạng giữa các thành phần được phân phối và chúng tôi cũng sử dụng XSLT để tạo các trang HTML của chúng tôi. Trước đây, chúng ta đi qua phân cấp của chúng ta để tạo một tài liệu XML (một chuỗi) và sau đó đã viết tài liệu XML đó vào một ổ cắm mạng hoặc nạp tài liệu đó cho công cụ XSLT (mà về cơ bản chỉ phân tích lại nó). Sau khi sử dụng kỹ thuật này, về cơ bản chúng tôi có thể cung cấp phân cấp đối tượng của chúng tôi (sử dụng bộ điều hợp SAX này) trực tiếp cho công cụ XSLT mà không cần chuỗi XML trung gian. Nó cũng thuận tiện để có thể sử dụng một trình xử lý nội dung để tạo ra một biểu diễn XML nhỏ gọn cho luồng mạng và sử dụng một trình khác để tạo một tài liệu XML được in đẹp để ghi vào một tệp nhật ký.

Ngoài ra, việc sử dụng API phân tích cú pháp SAX để viết XML là lạm dụng API, IMHO. - Puce 49 phút trước

Có lẽ, nhưng tôi nghĩ điều đó phụ thuộc vào nhu cầu của bạn. Nếu yêu cầu của OP chỉ là viết ra một tài liệu XML cụ thể, thì điều này chắc chắn là quá mức cần thiết. Tuy nhiên, tôi nghĩ nó đáng nói đến nếu OP sử dụng XML theo những cách khác trong dự án của anh ta mà anh ta không đề cập đến. Không có hại trong việc đưa ra một ý tưởng thay thế.

Gọi điện thoại là lạm dụng có thể hơi mạnh, nhưng tôi đồng ý rằng bạn được hưởng ý kiến ​​của mình. Tài liệu của nó trong một tài liệu hướng dẫn của Oracle, do đó, nó không được coi là lạm dụng bởi các kỹ sư Sun/Oracle. Rất thành công trong dự án của chúng tôi để giúp chúng tôi đáp ứng các yêu cầu của chúng tôi mà không có những nhược điểm đáng kể, vì vậy tôi sẽ giữ cách tiếp cận này trong hộp công cụ của tôi khi nó hữu ích trong tương lai.

+3

Điều này đúng, nhưng giao diện XMLStreamWriter được mô tả ở trên thân thiện với người dùng hơn nhiều. –

+0

Bên cạnh đó, việc sử dụng API phân tích cú pháp SAX để viết XML là việc lạm dụng API, IMHO. – Puce

+1

@Michael Kay - Cảm ơn nhận xét của bạn. Tôi đã cố làm rõ trong bản chỉnh sửa ở trên. –

32

Phân tích SAX là để đọc tài liệu chứ không phải viết tài liệu.

Bạn có thể viết XML với XMLStreamWriter:

OutputStream outputStream = new FileOutputStream(new File("doc.xml")); 

XMLStreamWriter out = XMLOutputFactory.newInstance().createXMLStreamWriter(
       new OutputStreamWriter(outputStream, "utf-8")); 

out.writeStartDocument(); 
out.writeStartElement("doc"); 

out.writeStartElement("title"); 
out.writeCharacters("Document Title"); 
out.writeEndElement(); 

out.writeEndElement(); 
out.writeEndDocument(); 

out.close(); 
+0

Tôi thích câu trả lời này, thật không may là gói đó không có sẵn trong Android. Lỗi của tôi vì đã không đề cập đến điều đó. D: – Lunchbox

+2

Ok, bạn cũng có thể in XML theo cách thủ công. 'out.print (" giá trị ");' vv Nhưng bạn phải đảm bảo thoát khỏi các giá trị đúng cách. Điều này có thể được thực hiện với apache commons 'StringEscapeUtils.escapeXML()'. Hoặc một số phương pháp khác. Nó phụ thuộc vào các giá trị có thể, có lẽ bạn chỉ có thể làm điều đó với regex. – morja

5

Dưới đây câu trả lời "một hướng dẫn tốt cho việc viết XML bằng cách sử dụng phân tích cú pháp SAX và Java" phần của câu hỏi

Tôi không chắc chắn nếu bạn đã trải qua điều này. Nhưng tôi thực sự thích Java's Really Big Index of Everything.

Đi qua này: http://download.oracle.com/javase/tutorial/jaxp/index.html

Và cuối cùng, điều này: http://download.oracle.com/javase/tutorial/jaxp/sax/index.html

+0

Cảm ơn Nishant. Đây là thông tin đầy đủ! Đây là những gì tôi đang tìm kiếm. – simpleDev

3

Cũng xem xét JAXB để viết/đọc XML.

4

Vui lòng tham khảo bài đăng trên blog cá nhân của tôi: XML Generation In Java - cụ thể, The SAX method. Nó tham khảo một số bài viết khác liên quan đến điều này, cung cấp một ví dụ cụ thể và so sánh SAX với các API phổ biến khác để tạo XML từ Java.

(Nhận ra đây là một câu hỏi cũ hơn, nhưng cảm thấy cần thiết để thêm câu hỏi này cho bất kỳ ai khác có thể có cùng một câu hỏi.)

1

Bạn cũng có thể cầu để TRAX với điều này:

public abstract class PipedSAXSource extends SAXSource { 
    protected PipedSAXSource() { 
    setXMLReader(new CallWriteDuringSax()); 
    } 

    protected abstract void writeTo(ContentHandler sink) 
     throws IOException, SAXException; 

    private class CallWriteDuringSax extends XMLFilterImpl { 
    @Override 
    public void parse(InputSource ignored) throws IOException, SAXException { 
     writeTo(getContentHandler()); 
    } 

    @Override 
    public void setFeature(String name, boolean value) {} 
    } 
} 

Sử dụng như sau:

public static void main(String[] args) throws Exception { 
    Source in = new PipedSAXSource() { 
     @Override 
     protected void writeTo(ContentHandler sink) throws SAXException { 
     sink.startDocument(); 

     sink.startElement("", "root", "root", new AttributesImpl()); 
     sink.endElement("", "root", "root"); 

     sink.endDocument(); 
     } 
    }; 

    Transformer identity = TransformerFactory.newInstance().newTransformer(); 
    identity.transform(in, new StreamResult(System.out)); 
    } 
Các vấn đề liên quan