2012-06-08 13 views
6

Hiện nay tôi đang marshalling một đối tượng JAXB tới luồng ra với đoạn mã sauLàm thế nào để có được những không gian tên của một đối tượng JAXB

marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); 
ByteArrayOutputStream out = new ByteArrayOutputStream(); 
marshaller.marshal(new JAXBElement(new QName("hard_coded_namespace", clazz.getSimpleName()), clazz, obj), out); 

Tôi muốn thay thế "hard_coded_namespace" với không gian tên chứa trong JAXB " obj "(hoặc một trong các thuộc tính của nó, chúng hiện nay nên chia sẻ cùng một NS).

Bất kỳ ý tưởng nào về cách nhận thông tin NS TRƯỚC KHI đầm lầy? Trong luồng đầu ra, các Không gian tên xuất hiện. Vì vậy, họ đang ở đâu đó trong "obj".

[CẬP NHẬT] Như được chỉ ra trong các câu trả lời bên dưới, tôi không cần đặt thuộc tính JAXB_FRAGMENT. Tôi đã thay đổi nó thành:

JAXB.marshal(new JAXBElement<T>(new QName("hard_coded_namespace", rootName), clazz, jaxbObject), out); 

Trả lời

4

Cho đến nay, đây là giải pháp tôi tìm thấy:

String nsURI = ""; 
    for(Annotation annotation: jaxbObject.getClass().getPackage().getAnnotations()){ 
     if(annotation.annotationType() == XmlSchema.class){ 
      nsURI = ((XmlSchema)annotation).namespace(); 
      break; 
     } 
    } 

giải pháp More thanh lịch được chào đón :-)

+1

thông tin không gian tên nằm trong 'package-info.java' – Chris

+1

tùy thuộc vào mục đích chung mà bạn muốn giải pháp của mình, không có gì đảm bảo rằng gói-thông tin. lớp sẽ được tạo bởi xjc (xem tùy chọn -npa). – kschneid

1

Bạn có cần sử dụng API nguyên soái đó không? Có một quá tải đơn giản hơn. Chừng nào lớp runtime obj vừa thể hiện @XmlRootElement chú thích, bạn sẽ có thể chỉ cần gọi

marshaller.marshal(obj, out); 
+0

Trong trường hợp này, tôi không có thuộc tính XmlRootElement được đặt trong lớp của đối tượng. API Marshaller là cần thiết để tôi có thể chỉ ra rằng đây là một JAXB_FRAGMENT, tức là một phần tử không có XmlRootElement. Nêu tôi sai vui long chân chỉnh tôi. – Chris

+0

Thực ra tôi đang làm chính xác những gì bạn đề nghị. Nó chỉ khó đọc vì JAXBElement mới() ở giữa ... :-). – Chris

1

Việc sử dụng các Marshaller.JAXB_FRAGMENT tài sản không thực sự có bất cứ điều gì để làm với xử lý các yếu tố không phải root. Nó hoạt động như một lá cờ để xác định xem các sự kiện marshaling nhất định có nên được điều chỉnh hay không. Ví dụ: nếu thuộc tính được đặt thì sự kiện tài liệu bắt đầu và kết thúc sẽ không được tạo.

tôi đã không kiểm tra những điều sau đây, nhưng đây là một ý tưởng cơ bản về cách tôi muốn tạo ra một số mã tiện ích để tìm ra QName của một đối tượng JAXB đưa ra:

  • Nếu JAXBIntrospector.isElement trả về true, sau đó chỉ cần sử dụng JAXBIntrospector.getElementName.
  • Sử dụng phản xạ để tìm một phương thức trên lớp ObjectFactory trong cùng một gói như đối tượng JAXB trả JAXBElement và mất một đối số duy nhất đó là một thể hiện của lớp tương tự như các đối tượng JAXB . Gọi phương thức đó và sau đó sử dụng JAXBElement.getName.
+0

cảm ơn câu trả lời của bạn! isElement() trả về false trên các đối tượng mà tôi đang xử lý. – Chris

+1

thì tốt, viên đạn thứ hai phải bao gồm điều kiện đó ... – kschneid

0
JAXBContext jaxbCtx = JAXBContext.newInstance(Instance.class); 
QName qname = jaxbCtx.createJAXBIntrospector().getElementName(instance); 
0

Nếu không có @XmlRootElement trên lớp serialize, không có cách nào khác để tìm kiếm bản khai gói (JAXBIntrospector sẽ không hoạt động):

private <T> QName getQName(final Class<T> clazz) { 
    // No other way since it is not @RootXmlElement 
    final String xmlns; 
    final Package aPackage = clazz.getPackage(); 
    if (aPackage.isAnnotationPresent(XmlSchema.class)) { 
     xmlns = aPackage.getDeclaredAnnotation(XmlSchema.class).namespace(); 
    } else { 
     xmlns = ""; // May throw illegal 
    } 
    return new QName(xmlns, clazz.getSimpleName()); 
}