Можно ли настроить префикс пространства имен, который JAXB использует при маршалировании в строку?

например, у меня есть простая схема, которая импортирует другой схеме. Вторая схема (urn:just: attributes, just-attributes.xsd) просто определяет группу атрибутов.

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.org/MySchema"
    xmlns:tns="http://www.example.org/MySchema" 
    elementFormDefault="qualified"
    xmlns:ja="urn:just:attributes">

    <import schemaLocation="just-attributes.xsd" namespace="urn:just:attributes"/>

    <element name="MyElement">
        <complexType>
            <attributeGroup ref="ja:AttributeGroup"/>
        </complexType>
    </element>
</schema>

Я использую задачу Metro xjc Ant для генерации классов из этой схемы. Проблема, с которой я сталкиваюсь, заключается в том, что стороннее приложение, с которым я взаимодействую, специфично для пространств имен. В этом случае мне нужно строковое значение, поэтому я должен сериализовать его. Я использую шаблонный код для этот.

private static <T> String marshal(T object) throws JAXBException{
    OutputStream outputStream = new ByteArrayOutputStream();
    JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.marshal(object, outputStream);
    return outputStream.toString();
}

что дает мне что-то вроде

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:MyElement xmlns:ns1="urn:just:attributes" xmlns:ns2="http://www.example.org/MySchema" ns1:attrib1="1234" ns1:attrib2="5678"/>

проблема в том, что эта третья сторона ожидает чего-то вроде xmlns:thirdpartyns="urn:just:attributes", то есть они анализируются на основе имя дано пространство имен. Это и быть "thirdpartyns" для их программного обеспечения для работы.

кто-нибудь знает способ обойти это, за исключением поиска и замены в результирующей строке? Правило пользовательской привязки возможно?

4 ответов


http://hwellmann.blogspot.com/2011/03/jaxb-marshalling-with-custom-namespace.html

Это показывает, как это сделать.

другой: http://www.systemmobile.com/?p=280

ключевые биты в случае, если эта ссылка тоже умирает:

класс NamespacePrefixMapper, найденный в com.солнце.XML.связывать.пакет маршаллера. Абстрактный класс имеет один метод для реализации:

public abstract String getPreferredPrefix(  
     String namespaceUri,         
     String suggestion,         
     boolean requirePrefix); 

затем

Marshaller marshaller =        
    jaxbContext.createMarshaller();        
marshaller.setProperty(”com.sun.xml.bind.namespacePrefixMapper”,        
    new MyNamespacePrefixMapper());  

Если вы кроме того, используя javax.XML.язык XPath.XPath, ваш NamespacePrefixMapper также может реализовать javax.XML.пространство имен.NamespaceContext, централизация настройки пространства имен в одном классе.


Я проверял это на Java SE6 и это требует небольшого изменения по сравнению с решением для Java SE 5 (как описано выше):

    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
    m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", mapper);

таким образом, третье свойство сверху содержит дополнительное .internal. в имени пакета по сравнению с версией Java SE5. Что то я не нашел, это как сказать Маршаллер что URI пространства имен становится пространством имен по умолчанию (""). Если я переопределю метод getPreferredPrefix () и верну пустая строка, Маршаллер имеет проблемы с написанием атрибутов пространства имен по умолчанию (в этом случае он создает новое пространство имен с именем ns1)


у меня был тот же вопрос. В package-info.java (если у вас его нет, вы можете просто вручную создать его) добавить xmlns детали:

@javax.xml.bind.annotation.XmlSchema(xmlns = {
        @javax.xml.bind.annotation.XmlNs(namespaceURI = "urn:just:attributes", prefix = "thirdpartyns") }, 
        elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)

есть способ сделать это, который использует внутренний класс реализации JAXB под названием NamespacePrefixMapper. В JAXB RI это в com.sun.xml.bind.marshaller, но в Java6, это в com.sun.xml.internal.bind.marshaller.

это абстрактный класс, который вы можете подкласс и реализовать абстрактный метод, который сопоставляет URI пространства имен для префикса.

затем вы вводите экземпляр этого подкласса в маршаллер:

JAXBContext context = ...
Marshaller marshaller = context.createMarshaller();
NamespacePrefixMapper prefixMapper = new MyPrefixMapperImpl();
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", prefixMapper);

имя свойства будет отличаться для версии Java6, но вы поняли идею.

обратите внимание, что это внутренний класс реализации JAXB, поэтому нет никакой гарантии, что он будет там в будущих версиях.