Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

EclipseLink/Examples/MOXy/XPath

Introduction

EclipseLink JAXB (MOXy) offers XPath based mapping which is what allows an existing object model to be mapped to an existing XML schema. This provides flexibility to users above and beyond the default JAXB mapping behavior.

Java Model

Below is the model (Customer & Address) we'll use, the get/set methods have been omitted to simplify the example.

Customer

@XmlRootElement
public class Customer {
 
   private Address billingAddress;
 
   private Address shippingAddress;
}

Address

public class Address {
 
    private String street;
 
}

Marshal to XML - Default behavior

Below is a code sample to marshal a Customer object along with the corresponding XML that would be created based on default JAXB rules.

Customer customer = new Customer();
 
Address billingAddress = new Address();
billingAddress.setStreet("1 Billing Street");
customer.setBillingAddress(billingAddress);
 
Address shippingAddress = new Address();
shippingAddress.setStreet("2 Shipping Road");
customer.setShippingAddress(shippingAddress);
 
JAXBContext jc = JAXBContext.newInstance(Customer.class); 
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(customer, System.out);
<customer>
   <billingAddress>
      <street>1 Billing Street</street>
   </billingAddress>
   <shippingAddress>
      <street>2 Shipping Road</street>
   </shippingAddress>
</customer>

Marshal to XML - MOXy Customization #1 - Grouping Element

Sometimes grouping elements are added to XML documents to organize data. JAXB has this concept for collection properties in the form of @XmlElementWrapper. The @XmlPath annotation can be used with non-collection properties for the same purpose. In this example the billing/shipping address data will be nested within the "contact-info" element.


@XmlRootElement
public class Customer {
 
   @XmlPath("contact-info/billing-address")
   private Address billingAddress;
 
   @XmlPath("contact-info/shipping-address")
   private Address shippingAddress;
 
}

In the resulting XML output the "billing-address" and "shipping-address" elements are nested inside the "contact-info" element.

<customer>
   <contact-info>
      <billing-address>
         <street>1 Billing Street</street>
      </billing-address>
      <shipping-address>
         <street>2 Shipping Road</street>
      </shipping-address>
   </contact-info>
<customer>

Marshal to XML - MOXy Customization #2 - Map by Position

Normally in JAXB elements with the same name must be mapped to a collection property. Using MOXy's path based mapping you map non-collection properties to a repeated element by index. In this case an @XmlPath annotation has been added to the pshippingAddress and billingAddress fields.

@XmlRootElement
public class Customer {
 
@XmlPath("address[1]")
private Address billingAddress;
 
@XmlPath("address[2]")
private Address shippingAddress;

In the resulting XML output both the shippingAddress and billingAddress are now marshaled to elements named "address"

<customer>
   <address>
      <street>1 Billing Street</street>
   </address>
   <address>
      <street>2 Shipping Road</street>
   </address>
</customer>

Marshal to XML - MOXy Customization #3 - Two Objects to the same node

MOXy can also be used to collapse the structure by mapping two objects to the same node. Again this is done using @XmlPath.

@XmlRootElement
public class Customer {
 
@XmlPath(".")
private Address billingAddress;
 
private Address shippingAddress;

In the resulting XML the billingAddress is now marshaled directly inside the customer element and the shippingAddress follows the default JAXB mapping rules.

<customer>
   <street>1 Billing Street</street>
   <shippingAddress>
      <street>2 Shipping Road<street>
   </shippingAddress>
</customer>

Specifying the XmlPath

In the examples above the XPath was set on the @XmlPath annotation. It could alternatively be set in an external bindings file if desired. Below is what the external bindings file would contain to map the addresses by position.

<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm">
   <java-types> 
      <java-type name="examples.Customer">
         <java-attributes>
            <xml-element java-attribute="shippingAddress" xml-path="address[1]"/>
            <xml-element java-attribute="billingAddress" xml-path="address[2]"/>
         </java-attributes>
      </java-type>
   </java-types>
</xml-bindings>

For more information on how to use and specify a bindings file see the EclipseLink-OXM.XML example

Back to the top