Matt
Matt

Reputation: 948

Unmarshal element attribute and text to separate fields with jaxb

How do I annotate the externalValue and companyId fields in the Root class so that "abc" gets mapped to externalValue and "123" gets mapped to companyId?
Do I need the @XmlJavaTypeAdapter annotation? Where? I'm hoping that if I do, it can just handle those 2 fields and I can leave the annotations for title and countryCodes as-is.

XML:

<item>
    <externalValue companyId="123">abc</externalValue>
    <title>My Title</title>
    <country>US</country>
    <country>CA</country>
</item>

POJO:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Item {
    private String externalValue;
    private String companyId;
    @XmlElement
    private String title;
    @XmlElement(name = "country")
    public List<String> countryCodes;

    // getters and setters...
}

Upvotes: 0

Views: 299

Answers (2)

pirho
pirho

Reputation: 12215

I am afraid that this is not possible to achieve only with annotations (so without extra POJO and some adapter) in general case namely JAXB specs. However if your happen to use MOXy as your JAXB implementation it is easy as adding annotation @XmlPath like this:

@XmlPath("externalValue/@companyId")
private String companyId;

Related question: Unmarshalling an XML using Xpath expression and jaxb

Upvotes: 1

Sambit
Sambit

Reputation: 8021

You have to define the class in the following manner.

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Item {

    private CompanyIdValue companyIdValue;
    @XmlElement
    private String title;

    @XmlElement(name = "country")
    public List<String> countryCodes;

    //getter and setter
}

In case of both attribute in an XML element tag, you have to define a separate class. Define a separate class called CompanyIdValue, for XML element, you have to define @XmlValue and for attribute you have to annotate with @XmlAttribute

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlValue;
public class CompanyIdValue {

    @XmlElement(name = "externalValue")
    private String externalValue;

    private String companyId;

    public String getExternalValue() {
        return externalValue;
    }

    @XmlValue
    public void setExternalValue(String externalValue) {
        this.externalValue = externalValue;
    }

    public String getCompanyId() {
        return companyId;
    }

    @XmlAttribute
    public void setCompanyId(String companyId) {
        this.companyId = companyId;
    }
}

I provide below a test program also for testing.

public class Test {
  public static void main(String[] args) {
    try {
      Item item = new Item();
      CompanyIdValue companyIdValue = new CompanyIdValue();
      companyIdValue.setCompanyId("SomeId");
      companyIdValue.setExternalValue("Some External value");
      item.setCompanyIdValue(companyIdValue);
      item.setCountryCodes(Arrays.asList("A", "B"));
      item.setTitle("Some Title");

      JAXBContext jaxbContext = JAXBContext.newInstance(Item.class);
      Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

      jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
      jaxbMarshaller.marshal(item, System.out);

    } catch (JAXBException e) {
      e.printStackTrace();
    }
  }
}

Upvotes: 0

Related Questions