Подтвердить что ты не робот

Можно ли настроить префикс пространства имен, который использует 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, чтобы сгенерировать классы из этой схемы. Проблема, с которой я сталкиваюсь, заключается в том, что стороннее приложение, с которым я взаимодействую, свойственно пространствам имен. В этом случае мне нужно значение String, поэтому я должен его сериализовать. Для этого я использую код шаблона.

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", то есть они анализируются на основе имени, заданного для пространства имен. Он имеет, чтобы быть "сторонними" для работы своего программного обеспечения.

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

4b9b3361

Ответ 1

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

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

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

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

класс NamespacePrefixMapper, найденный в пакете com.sun.xml.bind.marshaller. У абстрактного класса есть один способ реализации:

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.namespace.NamespaceContext, централизируя настройку пространства имен в одном классе.

Ответ 2

Я тестировал что в 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() и возвращу пустую строку, у Marshaller возникнут проблемы с написанием атрибутов пространства имен по умолчанию (в этом случае создается новое пространство имен ns1)

Ответ 3

У меня был тот же вопрос. В 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)

Ответ 4

Существует способ сделать это, в котором используется внутренний класс реализации 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, поэтому нет гарантии, что он будет в будущих версиях.