Один и тот же объект с разными отображениями в зависимости от контекста (MOXy)

Я использую EclipseLink MOXy в качестве JAXB (JSR-222) и мне нужна помощь с моим файлом сопоставления, чтобы маршалировать мои классы в XML .

Я использую внешний файл для отображения.

У меня есть два типа транзакций: A и B. Оба содержат объект заголовка (один и тот же объект) с двумя полями (текст1 и текст2).

При преобразовании их в XML я хотел бы, чтобы тег xml для полей заголовка транзакции A стал ‹headerA1> и ‹headerA2>, а для тех, которые связаны с транзакцией B, стал ‹headerB1> и ‹headerB2>.

Любая идея, как я могу это сделать (желательно без использования наследования)?

Вот код:

Класс ЗАГОЛОВОК

public class Header {

    private String text1;
    private String text2;

      public Header(){}

    public String getText1() {
        return text1;
    }

    public void setText1(String text1) {
        this.text1 = text1;
    }

    public String getText2() {
        return text2;
    }

    public void setText2(String text2) {
        this.text2 = text2;
    }

}

ТРАНЗАКЦИЯ А

public class TransactionA {

    private Header statementHeader;
    private BigDecimal units;
    private BigDecimal price;

    public TransactionA(){}

    public BigDecimal getUnits() {
        return units;
    }

    public void setUnits(BigDecimal units) {
        this.units = units;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public Header getStatementHeader() {
        return statementHeader;
    }

    public void setStatementHeader(Header statementHeader) {
        this.statementHeader = statementHeader;
    }

}

ТРАНЗАКЦИЯ B

public class TransactionB {

  private Header statementHeader;
    private BigDecimal units;
    private BigDecimal price;

    public TransactionB(){}

    public BigDecimal getUnits() {
        return units;
    }

    public void setUnits(BigDecimal units) {
        this.units = units;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public Header getStatementHeader() {
        return statementHeader;
    }

    public void setStatementHeader(Header statementHeader) {
        this.statementHeader = statementHeader;
    }

}

ФАЙЛ ОТОБРАЖЕНИЯ

<java-types>
  <java-type name="Statement" xml-accessor-type="NONE">
     <java-attributes>
        <xml-element java-attribute="tranA" />
        <xml-element java-attribute="tranB" />
     </java-attributes>
  </java-type>
  <java-type name="Header" xml-accessor-type="NONE">
     <java-attributes>
        <xml-element java-attribute="text1" name="headerA1" />
        <xml-element java-attribute="text2" name="headerA2" />
     </java-attributes>
  </java-type>
  <java-type name="TransactionA" xml-accessor-type="NONE">
     <java-attributes>
        <xml-element java-attribute="statementHeader" name="headerA" />
        <xml-element java-attribute="units" />
        <xml-element java-attribute="price"/>
     </java-attributes>
  </java-type>
  <java-type name="TransactionB" xml-accessor-type="NONE">
     <java-attributes>
        <xml-element java-attribute="statementHeader" name="headerB" />
        <xml-element java-attribute="units" />
        <xml-element java-attribute="price"/>
     </java-attributes>
  </java-type>
</java-types>

РЕЗУЛЬТАТ Как видите, теги для заголовка B такие же, как и для заголовка A.

<?xml version="1.0" encoding="UTF-8"?>
<tranA>
   <headerA>
      <headerA1>Description</headerA1>
      <headerA2>Units</headerA2>
   </headerA>
   <units>10</units>
   <price>99999999.98999999463558197021484375</price>
</tranA><tranB>
   <headerB>
      <headerA1>Bheader1</headerA1>
      <headerA2>Bheader2</headerA2>
   </headerB>
   <units>10</units>
   <price>99999999.98999999463558197021484375</price>
</tranB>

person Marcio J    schedule 21.12.2012    source источник


Ответы (1)


У нас уже давно открыт запрос на улучшение для такого типа поведения. Если бы вы могли проголосовать за следующее, но это помогло бы поднять его в нашем списке приоритетов.


КАК ВЫ МОЖЕТЕ СДЕЛАТЬ ЭТО СЕГОДНЯ

XmlAdapter (HeaderBAdapter)

Вы можете использовать XmlAdapter для предоставления альтернативного сопоставления для класса Header.

package forum13986357;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class HeaderBAdapter extends XmlAdapter<HeaderBAdapter.AdaptedHeaderB, Header>{

    public static class AdaptedHeaderB {
        public String headerB1;
        public String headerB2;
    }

    @Override
    public AdaptedHeaderB marshal(Header header) throws Exception {
        AdaptedHeaderB adaptedHeaderB = new AdaptedHeaderB();
        adaptedHeaderB.headerB1 = header.getText1();
        adaptedHeaderB.headerB2 = header.getText2();
        return adaptedHeaderB;
    }

    @Override
    public Header unmarshal(AdaptedHeaderB adaptedHeaderB) throws Exception {
        Header header = new Header();
        header.setText1(adaptedHeaderB.headerB1);
        header.setText2(adaptedHeaderB.headerB2);
        return header;
    }

}

oxm.xml

Ниже представлена ​​обновленная версия вашего картографического документа. Я обновил сопоставление свойства statementHeader в классе TransactionB, чтобы указать, что следует использовать XmlAdapter.

<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="forum13986357">
    <java-types>
        <java-type name="Statement" xml-accessor-type="NONE">
            <java-attributes>
                <xml-element java-attribute="tranA" />
                <xml-element java-attribute="tranB" />
            </java-attributes>
        </java-type>
        <java-type name="Header" xml-accessor-type="NONE">
            <java-attributes>
                <xml-element java-attribute="text1" name="headerA1" />
                <xml-element java-attribute="text2" name="headerA2" />
            </java-attributes>
        </java-type>
        <java-type name="TransactionA" xml-accessor-type="NONE">
            <java-attributes>
                <xml-element java-attribute="statementHeader" name="headerA" />
                <xml-element java-attribute="units" />
                <xml-element java-attribute="price" />
            </java-attributes>
        </java-type>
        <java-type name="TransactionB" xml-accessor-type="NONE">
            <java-attributes>
                <xml-element java-attribute="statementHeader" name="headerB">
                    <xml-java-type-adapter value="forum13986357.HeaderBAdapter" />
                </xml-element>
                <xml-element java-attribute="units" />
                <xml-element java-attribute="price" />
            </java-attributes>
        </java-type>
    </java-type

s>

jaxb.properties

Чтобы использовать MOXy в качестве провайдера JAXB, вам необходимо включить файл с именем jaxb.properties в тот же пакет, что и ваша модель домена, со следующей записью (http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as- ваш.html):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Демо

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

package forum13986357;

import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum13986357/oxm.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Statement.class}, properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StreamSource xml = new StreamSource("src/forum13986357/input.xml");
        JAXBElement<Statement> jaxbElement = unmarshaller.unmarshal(xml, Statement.class);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(jaxbElement, System.out);
    }

}

входной.xml/выходной

<?xml version="1.0" encoding="UTF-8"?>
<statement>
    <tranA>
        <headerA>
            <headerA1>Description</headerA1>
            <headerA2>Units</headerA2>
        </headerA>
        <units>10</units>
        <price>99999999.98999999463558197021484375</price>
    </tranA>
    <tranB>
        <headerB>
            <headerB1>Bheader1</headerB1>
            <headerB2>Bheader2</headerB2>
        </headerB>
        <units>10</units>
        <price>99999999.98999999463558197021484375</price>
    </tranB>

person bdoughan    schedule 21.12.2012