Jump to: navigation, search

Difference between revisions of "EclipseLink/Examples/MOXy/XPath"

m (Specifying the XmlPath)
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
 
==Introduction==
 
==Introduction==
EclipseLink JAXB (MOXy) offers XPath based mapping which is what allows an existing object model to be mapped to an existing XML schema.   
+
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==
 
==Java Model==
Line 55: Line 55:
 
</source>
 
</source>
  
==Marshal to XML - MOXy Customization #1 - Map by Position==
+
==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.
 +
 
 +
 
 +
<source lang="java">
 +
@XmlRootElement
 +
public class Customer {
 +
 +
  @XmlPath("contact-info/billing-address")
 +
  private Address billingAddress;
 +
 +
  @XmlPath("contact-info/shipping-address")
 +
  private Address shippingAddress;
 +
 +
}
 +
</source>
 +
 
 +
In the resulting XML output the "billing-address" and "shipping-address" elements are nested inside the "contact-info" element.
 +
<source lang="xml">
 +
<customer>
 +
  <contact-info>
 +
      <billing-address>
 +
        <street>1 Billing Street</street>
 +
      </billing-address>
 +
      <shipping-address>
 +
        <street>2 Shipping Road</street>
 +
      </shipping-address>
 +
  </contact-info>
 +
<customer>
 +
</source>
 +
 
 +
==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.
 
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.
  
Line 81: Line 112:
 
</source>
 
</source>
  
==Marshal to XML - MOXy Customization #2 - Two Objects to the same node==
+
==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.   
 
MOXy can also be used to collapse the structure by mapping two objects to the same node.  Again this is done using @XmlPath.   
  

Latest revision as of 14:48, 3 June 2011

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