2010-05-12 21 views
16

Tôi có một XML lặp lại khá lớn để tạo ra bằng cách sử dụng JAXB. Lưu trữ toàn bộ đối tượng trong bộ nhớ sau đó làm marshaling mất quá nhiều bộ nhớ. Về cơ bản, XML của tôi trông như thế này:Làm thế nào để sắp xếp không có không gian tên?

<Store> 
    <item /> 
    <item /> 
    <item /> 
..... 
</Store> 

Hiện nay giải pháp của tôi cho vấn đề là "mã cứng" thẻ gốc tới luồng ra, và sắp xếp mỗi người trong số các yếu tố lặp đi lặp lại từng người một:

aOutputStream.write("<?xml version="1.0"?>") 
aOutputStream.write("<Store>") 

foreach items as item 
    aMarshaller.marshall(item, aOutputStream) 
end 
aOutputStream.write("</Store>") 
aOutputStream.close() 

Bằng cách nào đó JAXB tạo ra XML như thế này

<Store xmlns="http://stackoverflow.com"> 
    <item xmlns="http://stackoverflow.com"/> 
    <item xmlns="http://stackoverflow.com"/> 
    <item xmlns="http://stackoverflow.com"/> 
..... 
</Store> 

Mặc dù đây là một XML hợp lệ, nhưng nó chỉ trông xấu xí, vì vậy tôi đang tự hỏi là có cách nào để nói với marshaller không đặt tên không gian cho các yếu tố mục? Hoặc là có cách nào tốt hơn để sử dụng JAXB để serialize để XML chunk bởi chunk?

+0

Thực tế việc triển khai và kết quả được đề xuất của bạn không khớp. Bạn đang tự viết thẻ gốc, tại sao không gian tên trong đầu ra trên phần tử gốc. – tkr

+0

Ahh bắt tốt. Bởi vì tôi thực sự sử dụng JAXB để "mã cứng" phần tử gốc. Vì vậy, những gì tôi đã làm là tôi tạo một đối tượng Root trống, sắp xếp nó thành một String, sau đó phân tích chuỗi để trích xuất các thẻ gốc. Vì vậy, nếu JAXB không tạo ra không gian tên cho thẻ gốc thì tôi phải chịu số phận. – Alvin

Trả lời

6

Sau đây đã làm các trick cho tôi:

  XMLStreamWriter writer = ... 
     writer.setNamespaceContext(new NamespaceContext() { 
      public Iterator getPrefixes(String namespaceURI) { 
       return null; 
      } 

      public String getPrefix(String namespaceURI) { 
       return ""; 
      } 

      public String getNamespaceURI(String prefix) { 
       return null; 
      } 
     }); 
+0

http://stackoverflow.com/questions/17222902/ remove-namespace-prefix-while-jaxb-marshalling đã giúp tôi –

1

Nếu bạn không chỉ định một không gian tên JaxB sẽ không viết một.

Yout có thể sử dụng Stax trên luồng, nếu strcuture của bạn không phức tạp.

+0

nhưng thực tế là tôi cần một không gian tên, nhưng chỉ ở cấp phần tử gốc. – Alvin

11

Kiểm tra package-info.java (trong gói chứa các lớp có chú giải jaxb của bạn). Có thuộc tính namespace của @XmlSchema tại đó.

Ngoài ra, có một thuộc tính namespace trong chú thích @XmlRootElement.

+0

Có cách nào để chỉ định trong tệp ràng buộc không đặt không gian tên trong package-info.java của tôi và chỉ đặt không gian tên trong @XmlRootElement không? – Alvin

+0

bạn có thể ghi đè nó trong '@ XmlRootElement', nhưng theo như tôi hiểu, bạn muốn xóa nó hoàn toàn. – Bozho

+0

Tôi đã thử thêm -npa nhưng nó sẽ không hoạt động trên jaxb2-maven-plugin vì một lý do nào đó. Tôi chỉ muốn làm cho thuộc tính không gian tên là "" trong gói-thông tin.java được tạo tự động. @XmlRootElement của tôi có không gian tên = "" nhưng vẫn còn khi nó được marshalled nó nhận được không gian tên hiện diện trong package-info.java. Toàn bộ chi tiết tại đây: http://stackoverflow.com/questions/15796063/remove-xmlns-attribute-from-the-root-element-while-marshalling-jaxb – icedek

6

Có một cách rất đơn giản để thoát khỏi các tiền tố không gian tên trong trường hợp của bạn: chỉ cần thiết lập các thuộc tính elementFormDefault để không đủ tiêu chuẩn trong lược đồ, như thế này:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     xmlns:your="http://www.stackoverflow.com/your/namespace"> 

Bạn sẽ nhận được tiền tố namespace chỉ trong thẻ đầu tiên:

<ns1:your xmlns:ns1="http://www.stackoverflow.com/your/namespace"> 

Tôi hy vọng điều này sẽ hữu ích.

Trân Pawel Procaj

+6

Điều này làm việc tuyệt vời nhưng có cách nào để loại bỏ không gian tên trong thẻ (root) đầu tiên không? – icedek

+0

Tôi đang tìm kiếm nó! Cảm ơn! –

1

Đối với tôi, chỉ cần gọi xmlStreamWriter.setDefaultNamespace("") giải quyết vấn đề này.

Một điều nữa bạn phải quan tâm để loại bỏ tiền tố không gian tên khỏi đầu ra là ở mọi nơi bạn có @XmlElement đảm bảo nó không bao gồm thuộc tính không gian tên như @XmlElement(name="", namespace"http://..."); nếu không, không có giải pháp nào hoạt động.

-2

này làm việc cho tôi:

marshaller.setProperty (Marshaller.JAXB_SCHEMA_LOCATION, "");

4

Tôi đã thử tất cả các giải pháp được cung cấp dưới dạng câu trả lời ở đây và không có giải pháp nào phù hợp với môi trường của tôi. Yêu cầu hiện tại của tôi là:

  1. jdk1.6.0_45
  2. Các lớp được chú thích JAXB được tạo khi mỗi lần tạo lại, do đó, thay đổi chúng không phải là một tùy chọn.

Tôi muốn chia sẻ với bạn kết quả thử nghiệm của tôi với các giải pháp tôi đã tìm thấy trên stackoverflow.

Tuỳ chỉnh NamespaceContextlink

đơn giản và thanh lịch giải pháp, nhưng trong môi trường của tôi, tôi có một ngoại lệ với stacktrace sau:

javax.xml.stream.XMLStreamException: Trying to write END_DOCUMENT when document has no root (ie. trying to output empty document). 

at com.ctc.wstx.sw.BaseStreamWriter.throwOutputError(BaseStreamWriter.java:1473) 
at com.ctc.wstx.sw.BaseStreamWriter.reportNwfStructure(BaseStreamWriter.java:1502) 
at com.ctc.wstx.sw.BaseStreamWriter.finishDocument(BaseStreamWriter.java:1663) 
at com.ctc.wstx.sw.BaseStreamWriter.close(BaseStreamWriter.java:288) 
at MyDataConverter.marshal(MyDataConverter.java:53) 

tôi đã bị mắc kẹt cố gắng tìm ra lý do tại sao ngoại lệ này xảy ra và quyết định thử cái gì khác.

Sửa đổi package-info.javalink

Giải pháp đơn giản nhất tôi đã tìm thấy. Nó thường hoạt động, nhưng tập tin này được tạo ra trên mỗi bản dựng. Đó là lý do tại sao tôi phải tìm một giải pháp khác.

Schema VỀ VIỆC SỬA ĐỔIlink

trình như mô tả nhưng không giải quyết vấn đề của tôi. Tôi vẫn có một không gian tên trong phần tử gốc.

DelegatingXMLStreamWriterlink

Tôi cũng đã cố gắng giải pháp được nêu ở đó, nhưng tôi đã có một sự khẳng định lạ trong com.sun.xml.bind.v2.runtime.output.NamespaceContextImpl (phương pháp declareNsUri) mà tôi đã thất bại trong việc đánh bại.

Giải pháp của tôi

Trong khi nghiên cứu vấn đề này với khẳng định tôi phải thực hiện phiên bản riêng của tôi về XMLStreamWriter dựa trên DelegatingXMLStreamWriter.java

public class NamespaceStrippingXMLStreamWriter extends DelegatingXMLStreamWriter { 

    public NamespaceStrippingXMLStreamWriter(XMLStreamWriter xmlWriter) throws XMLStreamException { 
    super(xmlWriter); 
    } 

    @Override 
    public void writeNamespace(String prefix, String uri) throws XMLStreamException { 
    // intentionally doing nothing 
    } 

    @Override 
    public void writeDefaultNamespace(String uri) throws XMLStreamException { 
    // intentionally doing nothing 
    } 

    @Override 
    public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException { 
    super.writeStartElement(null, local, null); 
    } 

    @Override 
    public void writeStartElement(String uri, String local) throws XMLStreamException { 
    super.writeStartElement(null, local); 
    } 

    @Override 
    public void writeEmptyElement(String uri, String local) throws XMLStreamException { 
    super.writeEmptyElement(null, local); 
    } 

    @Override 
    public void writeEmptyElement(String prefix, String local, String uri) throws XMLStreamException { 
    super.writeEmptyElement(null, local, null); 
    } 

    @Override 
    public void writeAttribute(String prefix, String uri, String local, String value) throws XMLStreamException { 
    super.writeAttribute(null, null, local, value); 
    } 

    @Override 
    public void writeAttribute(String uri, String local, String value) throws XMLStreamException { 
    super.writeAttribute(null, local, value); 
    } 
} 

Ý tưởng chính là để tránh chuyển thông tin không gian tên cho XMLStreamWriter cơ bản . Hy vọng điều này sẽ giúp bạn tiết kiệm thời gian giải quyết vấn đề tương tự.

PS. Nó không cần thiết để mở rộng DelegatingXMLStreamWriter trong mã của bạn. Tôi đã thực hiện điều này để cho thấy phương pháp nào cần thay đổi.

+0

Tính năng này hoạt động tốt trong trường hợp có nhiều không gian tên +1 –

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