2012-06-08 4 views
6

В настоящее время я сортировочная объект JAXB в выходной поток с помощью следующего кодаКак получить пространство имен объекта 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); 

Я хотел бы заменить «hard_coded_namespace» с пространством имен, содержащихся в JAXB " obj "(или один из его атрибутов, в настоящее время они должны иметь один и тот же NS).

Любые идеи о том, как добраться до информации NS до маршалинга? В выходном потоке появляются пространства имен. Поэтому они находятся где-то в «obj».

[UPDATE] Как указано в ответах ниже, мне не нужно устанавливать свойство JAXB_FRAGMENT. Я изменил его на:

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

ответ

4

В настоящем время, это решение, которое я нашел:

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

Более элегантных решений приветствуются :-)

+1

информация о пространстве имен была в 'package-info.java' – Chris

+1

в зависимости от того, как вы хотите, чтобы ваше решение было универсальным, нет никакой гарантии, что пакет-информация. класс будет генерироваться xjc (см. параметр -npa). – kschneid

1

Нужно ли использовать этот API-интерфейс маршала? Простейшая перегрузка. Пока OBJ в класс во время выполнения имеет аннотацию @XmlRootElement, вы должны быть в состоянии просто позвонить

marshaller.marshal(obj, out); 
+0

В этом случае у меня нет атрибута XmlRootElement, установленного в классе объекта. API-интерфейс Marshaller необходим, чтобы я мог указать, что это JAXB_FRAGMENT, то есть элемент без XmlRootElement. Пожалуйста, поправьте меня, если я ошибаюсь. – Chris

+0

На самом деле я делаю именно то, что вы рекомендуете. Это просто трудно прочитать из-за нового JAXBElement() в середине ... :-). – Chris

1

Использование в Marshaller.JAXB_FRAGMENT собственности на самом деле не имеет ничего общего с обработкой некорневых элементов. Он действует как флаг, чтобы определить, должны ли быть ограничены определенные события маршалинга. Например, если свойство установлено, то начальные и конечные события документа не будут сгенерированы.

Я не проверял следующее, но вот основная идея о том, как я бы создать какой-то вспомогательный код, чтобы найти QName данного JAXB объекта:

  • Если JAXBIntrospector.isElement возвращает истину, а затем просто использовать JAXBIntrospector.getElementName.
  • Используйте отражение, чтобы найти метод на ObjectFactory класса в же пакете, что и объект JAXB, который возвращает JAXBElement и принимает один аргумент, который является экземпляром того же класса, что и объект JAXB . Вызовите этот метод, а затем используйте JAXBElement.getName.
+0

Спасибо за ваш ответ! isElement() возвращает false для объектов, с которыми я имею дело. – Chris

+1

это нормально, вторая пуля должна покрыть это условие ... – kschneid

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

Если нет @XmlRootElement от класса к сериализовать, нет другого способа поиска самой декларации пакета (JAXBIntrospector не будет работать):

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()); 
} 
Смежные вопросы