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