具有不同映射的相同对象,具体取决于上下文(MOXy)

时间:2012-12-21 08:01:46

标签: jaxb eclipselink moxy

我正在使用 EclipseLink MOXy 作为我的JAXB (JSR-222)提供程序,并需要我的映射文件的一些帮助,以便将我的类封送到XML中。

我正在使用外部文件进行映射。

我有两种类型的交易: A和B 。 两者都包含一个标题对象(同一个对象),包含两个字段(text1和text2)。

当将这些编组为XML时,我希望transactionA标题的字段的xml标记变为< headerA1>和< headerA2>,以及与transactionB链接的< headerB1>和< headerB2>。

知道如何实现这一目标(最好不使用继承)?

以下是代码:

HEADER Class

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;
    }

}

交易A

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>

1 个答案:

答案 0 :(得分:0)

我们已经暂时针对此类行为打开了增强请求。如果您可以对以下内容进行投票,但这有助于将其提升到我们的优先级列表中。


您今天可以做什么

XmlAdapter(HeaderBAdapter)

您可以使用XmlAdapterHeader类提供替代映射。

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-your.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);
    }

}

<强> input.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>