Не видя вашей фактической схемы XML, файлов и сгенерированных JAXB классов (и их аннотаций), я могу только посоветовать вам попробовать адаптировать следующий пример к вашему сценарию.
Учитывая, что у вас есть сгенерированный JAXB класснапример:
@XmlRootElement(namespace = "http://test.com")
@XmlType(namespace = "http://test.com")
public static final class Test {
public String data;
public Test() {}
}
, который находится в пакете test
и в нем есть файл package-info.java
, например:
@XmlSchema(elementFormDefault = XmlNsForm.QUALIFIED,
xmlns = @XmlNs(prefix = "", namespaceURI = "http://test.com"))
package test;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
следующий код:
Test test = new Test();
test.data = "Hello, World!";
JAXBContext context = JAXBContext.newInstance(Test.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(test, System.out);
напечатает это:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<test xmlns="http://test.com">
<data>Hello, World!</data>
</test>
Вероятно, вы, вероятно, можете полностью пропустить реализацию NamespacePrefixMapper
.
Играть с пропуском определенных namespace
элементов из любого изаннотации и посмотрите, как изменится вывод.
Блейз Дафан (эксперт по связыванию Java XML, вероятно, скрывающийся где-то возле ) опубликовал некоторую информацию по этой проблеме на своемблог, см. его пост для получения дополнительной информации.
На основе информации, предоставленной Баптистом в чате, я предлагаю следующее решение (я думаю, это наиболее безболезненно).
Скомпилируйте ваши файлы схемы с помощью XJC в обычном режиме ($ xjc .
).Это создаст package-java.info
файлов для каждого из сгенерированных пакетов.Я предполагаю, что эта схема не обновляется каждый день, поэтому вы можете вносить изменения в файлы package-info.java
(даже если в этих файлах будут некоторые строчные комментарии, говорящие о том, что вам не следует это делать - в любом случае, делайте это).Если схема обновляется, и вам необходимо перекомпилировать ее, запустите XJC с ключом -npa
, который говорит, что он не должен автоматически генерировать эти package-info.java
файлы, поэтому (в идеале) вы не можете перезаписать файлы, созданные вручную (если вы используете контроль версий, вы можете / должны включить эти файлы (ручной работы) в репозиторий).
На основе предоставленных файлов схемы создаются четыре пакета, поэтому я включу мою версию измененного package-info.java
файлы.
@XmlSchema(namespace = "http://www.ebics.org/H000",
xmlns = @XmlNs(prefix = "ns1",
namespaceURI = "http://www.ebics.org/H000"))
package org.ebics.h000;
@XmlSchema(namespace = "http://www.ebics.org/H003",
xmlns = @XmlNs(prefix = "",
namespaceURI = "http://www.ebics.org/H003"))
package org.ebics.h003;
@XmlSchema(namespace = "http://www.ebics.org/S001",
xmlns = @XmlNs(prefix = "ns3",
namespaceURI = "http://www.ebics.org/S001"))
package org.ebics.s001;
@XmlSchema(namespace = "http://www.w3.org/2000/09/xmldsig#",
xmlns = @XmlNs(prefix = "ns2",
namespaceURI = "http://www.w3.org/2000/09/xmldsig#"))
package org.w3._2000._09.xmldsig;
После этого вы создаете свой JAXBContext
следующим образом:
JAXBContext context =
JAXBContext.newInstance("org.ebics.h003:org.ebics.s001:org.w3._2000._09.xmldsig");
(я заметил, что вы на самом деле не используете h000
package, поэтому я исключил его из списка имен пакетов. Если он включен, то корневой маршалированный XML-тег, вероятно, будет содержать его пространство имен и префикс, даже если он не используется.)
После этого вы отменяете входной XML-код и делаете все, что хотите, с объектом в памяти.
Unmarshaller unmarshaller = context.createUnmarshaller();
EbicsNoPubKeyDigestsRequest ebicsNoPubKeyDigestsRequest =
(EbicsNoPubKeyDigestsRequest) unmarshaller.unmarshal(stream);
Теперь, если вы хотите маршалировать только тег header
, который вложен в ebicsNoPubKeyDigestsRequest
у тебя естье, чтобы обернуть его внутри JAXBElement<...>
, потому что тип header
EbicsNoPubKeyDigestsRequest.Header
не аннотирован @XmlRootElement
аннотацией.У вас есть два (в этом случае одном ) способа создания этого элемента.
Создайте экземпляр ObjectFactory
для соответствующего пакета и используйте его функцию JAXBElement<T> createT(T t)
,Который оборачивает свой ввод в JAXBElement<...>
.К сожалению, однако, для типа поля header
(с учетом ваших файлов схемы) XJC не генерирует такой метод, поэтому вы должны сделать это вручную.
В принципе вы почти все сделали правильно, но при созданииJAXBElement<...>
вместо его передачи new QName("header")
вам нужно создать полностью определенное имя, что означает, что пространство имен также указано.Передача только имени тега XML недостаточна, поскольку JAXB не будет знать, что этот конкретный тег header
является частью пространства имен "http://www.ebics.org/H003"
.Сделайте это следующим образом:
QName qualifiedName = new QName("http://www.ebics.org/H003", "header");
JAXBElement<EbicsNoPubKeyDigestsRequest.Header> header =
new JAXBElement<EbicsNoPubKeyDigestsRequest.Header>(
qualifiedName, EbicsNoPubKeyDigestsRequest.Header.class, header);
Я не проверял, решает ли ваша проблема только изменение экземпляра QName
, но, возможно, так и будет.Однако я думаю, что этого не произойдет, и вам придется вручную управлять своими префиксами, чтобы получить хороший и последовательный результат.