blob: 33edbb70ed78d37e109c58dfcc4690b896f98f65 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>Using XPath Predicates for Mapping | EclipseLink 2.7 Understanding EclipseLink</title>
<meta name="generator" content="Oracle DARB XHTML Converter (Mode = document) - Version 1.0.22 Build 1" />
<meta name="date" content="2014-06-10T10:35:15Z" />
<meta name="robots" content="noarchive" />
<meta name="doctitle" content="Using XPath Predicates for Mapping" />
<meta name="relnum" content="Release 2.7" />
<link rel="stylesheet" type="text/css" href="../../dcommon/style.css" media="screen" />
<link rel="copyright" href="../../dcommon/html/cpyr.htm" title="Copyright" type="text/html" />
<link rel="start" href="../../index.htm" title="Home" type="text/html" />
<link rel="contents" href="toc.htm" title="Contents" type="text/html" />
<link rel="prev" href="jpatoxml004.htm" title="Previous" type="text/html" />
<link rel="next" href="jpatoxml006.htm" title="Next" type="text/html" />
<!-- START: Disqus --><script type="text/javascript"> var disqus_developer = 0; </script><!-- END: Disqus --><!-- START: Sharethis --><script type="text/javascript">var switchTo5x=true;</script><script type="text/javascript" src="http://w.sharethis.com/button/buttons.js"></script><script type="text/javascript" src="http://s.sharethis.com/loader.js"></script> <!-- END: Sharethis --></head>
<body bgcolor="#FFFFFF"><iframe id="docheader" frameborder="0" framemargin="0" scrolling="no" src="../../dcommon/header.html"></iframe><script src="http://www.google.com/jsapi" type="text/javascript"></script><script type="text/javascript"> google.load('search', '1', {language : 'en'}); google.setOnLoadCallback(function() { var customSearchOptions = {}; var googleAnalyticsOptions = {}; googleAnalyticsOptions['queryParameter'] = 'q'; googleAnalyticsOptions['categoryParameter'] = ''; customSearchOptions['googleAnalyticsOptions'] = googleAnalyticsOptions; var customSearchControl = new google.search.CustomSearchControl( '016171230611334810008:enkkfjmsqju', customSearchOptions); customSearchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET); var options = new google.search.DrawOptions(); options.setSearchFormRoot('cse-search-form'); customSearchControl.draw('cse', options); }, true);</script><link rel="stylesheet" href="http://www.google.com/cse/style/look/default.css" type="text/css" /><div id="cse" style="width:100%;"></div>
<div class="header"><a id="top" name="top"></a>
<table class="simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td align="left" valign="top"><font face="helvetica, arial, sans-serif"><b>EclipseLink Solutions Guide for EclipseLink</b><br />
Release 2.7</div></td>
<td valign="bottom" align="right" width="144">
<table class="simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td>&nbsp;</td>
<td align="center" valign="top"><a href="toc.htm"><img src="../../dcommon/images/contents.png" alt="Go To Table Of Contents" border="0" height="16" width="16" /><br />
</td><td>&nbsp;</td><td align="center"><a href="../../" target="_top" class="external text" title="Search" rel="nofollow"><img src="../../dcommon/images/search.png" alt="Search" style="border:0;" /><br /><span class="mini"></span></a></td><td>&nbsp;</td><td align="center"><a href="../eclipselink_otlcg.pdf" title="PDF" target="_blank"><img src="../../dcommon/images/pdf_icon.png" style="padding-right:5px;border:0" alt="PDF"></a></td>
</tr>
</table>
</td>
</tr>
</table>
<hr />
<table class="navigation simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="100" align="center">
<tr>
<td align="center"><a href="jpatoxml004.htm"><img src="../../dcommon/images/larrow.png" alt="Previous" border="0" height="16" width="16" /></a></td>
<td align="center"><a href="jpatoxml006.htm"><img src="../../dcommon/images/rarrow.png" alt="Next" border="0" height="16" width="16" /></a></td>
<td>&nbsp;</td>
</tr>
</table>
</div>
<!-- class="header" -->
<div class="ind"><!-- End Header --><a id="BEIBFCFC" name="BEIBFCFC"></a><a id="TLADG355" name="TLADG355"></a>
<div class="sect1"><!-- infolevel="all" infotype="General" -->
<h1 class="sect1"><font face="arial, helvetica, sans-serif" color="#330099">Using XPath Predicates for Mapping</font></h1>
<p>This section demonstrates how the EclipseLink MOXy API uses XPath predicates to define an expression that specifiers the XML element's name. An XPath predicate is an expression that defines a specific object-to-XML mapping. As shown in previous examples, by default, JAXB will use the Java field name as the XML element name.</p>
<p>This section contains the following subsections:</p>
<ul>
<li>
<p><a href="#BEIHJHCJ">Understanding XPath Predicates</a></p>
</li>
<li>
<p><a href="#BEIIBJHE">Mapping Based on Position</a></p>
</li>
<li>
<p><a href="#BEIJIHCI">Mapping Based on an Attribute Value</a></p>
</li>
<li>
<p><a href="#BEIDJHFD">"Self" Mappings</a></p>
</li>
</ul>
<a id="BEIHJHCJ" name="BEIHJHCJ"></a><a id="TLADG356" name="TLADG356"></a>
<div class="sect2"><!-- infolevel="all" infotype="General" -->
<h2 class="sect2"><font face="arial, helvetica, sans-serif" color="#330099">Understanding XPath Predicates</font></h2>
<p>As described above, an XPath predicate is an expression that defines a specific object-to-XML mapping when standard annotations</p>
<p>re not sufficient. For example, the following snippet of XML shows a <code>&lt;data&gt;</code> element with two <code>&lt;node&gt;</code> sub-elements. If you wanted to create this mapping in a Java object, you would need to specify an XPath predicate for each <code>&lt;node&gt;</code> sub-element; for example, <code>Node[2]</code> in the following Java:</p>
<pre xml:space="preserve" class="oac_no_warn">
&lt;java-attributes&gt;
&lt;xml-element java-attribute="node" xml-path="node[1]/ABC"/&gt;
&lt;xml-element java-attribute="node" xml-path=<strong>"node[2]/DEF"</strong>/&gt;
&lt;/java-attributes&gt;
</pre>
<p>would match the second occurrence of the node element (<code>"DEF"</code>) in the following XML:</p>
<pre xml:space="preserve" class="oac_no_warn">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;data&gt;
&lt;node&gt;ABC&lt;/node&gt;
<strong>&lt;node&gt;DEF&lt;/node&gt;</strong>
&lt;/data&gt;
</pre>
<p>Thus, by using the XPath predicate, you can use the same attribute name for a different attribute value.</p>
</div>
<!-- class="sect2" -->
<a id="BEIIBJHE" name="BEIIBJHE"></a><a id="TLADG357" name="TLADG357"></a>
<div class="sect2"><!-- infolevel="all" infotype="General" -->
<h2 class="sect2"><font face="arial, helvetica, sans-serif" color="#330099">Mapping Based on Position</font></h2>
<p>This mapping technique is described in <a href="jpatoxml003.htm#BEIDCEHD">Mapping Values to a Text Node by Position</a>.</p>
</div>
<!-- class="sect2" -->
<a id="BEIJIHCI" name="BEIJIHCI"></a><a id="TLADG358" name="TLADG358"></a>
<div class="sect2"><!-- infolevel="all" infotype="General" -->
<h2 class="sect2"><font face="arial, helvetica, sans-serif" color="#330099">Mapping Based on an Attribute Value</font></h2>
<p>Beginning with EclipseLink MOXy 2.3, you can also map to an XML element based on an Attribute value. In this exercise, you will annotate the JPA entity to render the XML document shown in <a href="#BEIIBGBB">Example 15-21</a>. Note that all of the XML elements are named node but are differentiated by the value of their name attribute.</p>
<div class="example"><a id="BEIIBGBB" name="BEIIBGBB"></a><a id="TLADG359" name="TLADG359"></a>
<p><strong><em><font face="arial, helvetica, sans-serif">Example 15-21</font></em></strong></p>
<pre xml:space="preserve" class="oac_no_warn">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;node&gt;
&lt;node name="first-name"&gt;Bob&lt;/node&gt;
&lt;node name="last-name"&gt;Smith&lt;/node&gt;
&lt;node name="address"&gt;
&lt;node name="street"&gt;123 A Street&lt;/node&gt;
&lt;/node&gt;
&lt;node name="phone-number" type="work"&gt;555-1111&lt;/node&gt;
&lt;node name="phone-number" type="cell"&gt;555-2222&lt;/node&gt;
&lt;/node&gt;
</pre></div>
<!-- class="example" -->
<p>To attain this mapping, you need to declare three classes, <code>Name</code>, <code>Address</code>, and <code>PhoneNumber</code> and then use an XPath in the form of <em><code>element-name</code></em><code>[@</code><em><code>attribute-name</code></em><em><code>='</code></em><em><code>value</code></em><code>']</code> to map each Java field.</p>
<a id="BEIEIFGA" name="BEIEIFGA"></a><a id="TLADG360" name="TLADG360"></a>
<div class="sect3"><!-- infolevel="all" infotype="General" -->
<h3 class="sect3"><font face="arial, helvetica, sans-serif" color="#330099">Task 1: Create the Customer Entity</font></h3>
<p>To create the <code>Customer</code> class entity:</p>
<ol>
<li>
<p>Import the necessary JPA packages by adding the following code:</p>
<pre xml:space="preserve" class="oac_no_warn">
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
</pre></li>
<li>
<p>Declare the <code>Customer</code> class and use the <code>@XmlRootElement</code> annotation to make it the root element. Set the XML accessor type to <code>FIELD</code>:</p>
<pre xml:space="preserve" class="oac_no_warn">
<strong>@XmlRootElement</strong>
@XmlAccessorType(XmlAccessType.FIELD)
<strong>public class Customer</strong> {
</pre></li>
<li>
<p>Declare local to the <code>Customer</code> class these properties:</p>
<ul>
<li>
<p><code>firstName</code> (String type)</p>
</li>
<li>
<p><code>lastName</code> (String)</p>
</li>
<li>
<p><code>Address</code> (Address)</p>
</li>
</ul>
<p>For each property, set the Xpath predicate by preceding the property declaration with the annotation <code>@XmlPath(</code><em><code>element-name</code></em><code>[@</code><em><code>attribute-name</code></em><code>='</code><em><code>value</code></em><em><code>'])</code></em>; for example, for <code>firstName</code>, you would set the XPath predicate with this statement:</p>
<pre xml:space="preserve" class="oac_no_warn">
@XmlPath("node[@name='first-name']/text()")
</pre></li>
<li>
<p>Also local to the <code>Customer</code> class, declare the <code>phoneNumber</code> property as a <code>List&lt;PhoneNumber&gt;</code> type and assign it the value <code>new ArrayList&lt;PhoneNumber&gt;()</code>.</p>
</li>
</ol>
<p>The <code>Customer</code> class should look like the snippet in <a href="#BEIHAHJF">Example 15-22</a>.</p>
<div class="example"><a id="BEIHAHJF" name="BEIHAHJF"></a><a id="TLADG361" name="TLADG361"></a>
<p><strong><em><font face="arial, helvetica, sans-serif">Example 15-22 Customer Object Mapping to an Attribute Value</font></em></strong></p>
<pre xml:space="preserve" class="oac_no_warn">
package example;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement(name="node")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlPath("node[@name='first-name']/text()")
private String firstName;
@XmlPath("node[@name='last-name']/text()")
private String lastName;
@XmlPath("node[@name='address']")
private Address address;
@XmlPath("node[@name='phone-number']")
private List&lt;PhoneNumber&gt; phoneNumbers = new ArrayList&lt;PhoneNumber&gt;();
...
}
</pre></div>
<!-- class="example" --></div>
<!-- class="sect3" -->
<a id="TLADG362" name="TLADG362"></a>
<div class="sect3"><!-- infolevel="all" infotype="General" --><a id="sthref120" name="sthref120"></a>
<h3 class="sect3"><font face="arial, helvetica, sans-serif" color="#330099">Task 2: Create the Address Entity</font></h3>
<p>To create the <code>Address</code> class, do the following:</p>
<ol>
<li>
<p>Import the necessary JPA packages by adding the following code:</p>
<pre xml:space="preserve" class="oac_no_warn">
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
</pre></li>
<li>
<p>Declare the <code>Address</code> class and set the XML accessor type to <code>FIELD</code>:</p>
<pre xml:space="preserve" class="oac_no_warn">
@XmlAccessorType(XmlAccessType.FIELD)
<strong>public class Address</strong> {
</pre>
<p>This instance does not require the <code>@XmlRootElement</code> annotation as in the previous Tasks because the <code>Address</code> class is root not a root element in the XML document.</p>
</li>
<li>
<p>Declare local to the <code>Address</code> class the <code>String</code> property <code>street</code>. Set the XPath predicate by preceding the property declaration with the annotation <code>@XmlPath("node[@name='street']/text()")</code>.</p>
</li>
</ol>
<p>The <code>Address</code> class should look like <a href="#BEIHAIHA">Example 15-23</a>.</p>
<div class="example"><a id="BEIHAIHA" name="BEIHAIHA"></a><a id="TLADG363" name="TLADG363"></a>
<p><strong><em><font face="arial, helvetica, sans-serif">Example 15-23 Address Object Mapping to an Attribute Value</font></em></strong></p>
<pre xml:space="preserve" class="oac_no_warn">
package example;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlAccessorType(XmlAccessType.FIELD)
public class Address {
@XmlPath("node[@name='street']/text()")
private String street;
...
}
</pre></div>
<!-- class="example" --></div>
<!-- class="sect3" -->
<a id="TLADG364" name="TLADG364"></a>
<div class="sect3"><!-- infolevel="all" infotype="General" --><a id="sthref121" name="sthref121"></a>
<h3 class="sect3"><font face="arial, helvetica, sans-serif" color="#330099">Task 3: Create the PhoneNumber Entity</font></h3>
<p>To create the <code>PhoneNumber</code> entity:</p>
<ol>
<li>
<p>Import the necessary JPA packages by adding the following code:</p>
<pre xml:space="preserve" class="oac_no_warn">
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
</pre></li>
<li>
<p>Declare the <code>PhoneNumber</code> class and use the <code>@XmlRootElement</code> annotation to make it the root element. Set the XML accessor type to <code>FIELD</code>:</p>
<pre xml:space="preserve" class="oac_no_warn">
<strong>@XmlRootElement</strong>
@XmlAccessorType(XmlAccessType.FIELD)
<strong>public class Customer</strong> {
</pre></li>
<li>
<p>Create the type and string properties and define their mapping as attributes under the PhoneNumber root element by using the <code>@XmlAttribute</code>. annotation.</p>
<pre xml:space="preserve" class="oac_no_warn">
@XmlAttribute
private String type;
@XmlValue
private String number;
</pre></li>
</ol>
<p>The <code>PhoneNumber</code> object should look like <a href="#BEIDDBJA">Example 15-24</a>.</p>
<div class="example"><a id="BEIDDBJA" name="BEIDDBJA"></a><a id="TLADG365" name="TLADG365"></a>
<p><strong><em><font face="arial, helvetica, sans-serif">Example 15-24 PhoneNumber Object Mapping to an Attribute Value</font></em></strong></p>
<pre xml:space="preserve" class="oac_no_warn">
package example;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {
@XmlAttribute
private String type;
@XmlValue
private String number;
...
}
</pre></div>
<!-- class="example" --></div>
<!-- class="sect3" --></div>
<!-- class="sect2" -->
<a id="BEIDJHFD" name="BEIDJHFD"></a><a id="TLADG366" name="TLADG366"></a>
<div class="sect2"><!-- infolevel="all" infotype="General" -->
<h2 class="sect2"><font face="arial, helvetica, sans-serif" color="#330099">"Self" Mappings</font></h2>
<p>A "self" mapping occurs on one-to-one mappings when you set the target object's XPath to "." (dot) so the data from the target object appears inside the source object's XML element. This exercise uses the example in <a href="#BEIJIHCI">Mapping Based on an Attribute Value</a> to map the Address information to appear directly under the customer element and not wrapped in its own element.</p>
<p>To create the self mapping:</p>
<ol>
<li>
<p>Repeat Tasks 1 and 2 in <a href="#BEIEIFGA">Task 1: Create the Customer Entity</a>.</p>
</li>
<li>
<p>Declare local to the <code>Customer</code> class these properties:</p>
<ul>
<li>
<p><code>firstName</code> (String type)</p>
</li>
<li>
<p><code>lastName</code> (String)</p>
</li>
<li>
<p><code>Address</code> (Address)</p>
</li>
</ul>
</li>
<li>
<p>For the <code>firstName</code> and <code>lastName</code> properties, set the XmlPath annotation by preceding the property declaration with the annotation <code>@XmlPath(</code><em><code>element-name</code></em><code>[@</code><em><code>attribute-name</code></em><code>='</code><em><code>value</code></em><em><code>'])</code></em>; for example, for <code>firstName</code>, you would set the XPath predicate with this statement:</p>
<pre xml:space="preserve" class="oac_no_warn">
@XmlPath("node[@name='first-name']/text()")
</pre></li>
<li>
<p>For the <code>address</code> property, set <code>@XmlPath</code> to "." (dot):</p>
<pre xml:space="preserve" class="oac_no_warn">
@XmlPath(".")
private Address address;
</pre></li>
<li>
<p>Also local to the <code>Customer</code> class, declare the <code>phoneNumber</code> property as a <code>List&lt;PhoneNumber&gt;</code> type and assign it the value <code>new ArrayList&lt;PhoneNumber&gt;()</code>.</p>
</li>
</ol>
<p>The rendered XML for the Customer entity would look like <a href="#BEICAHDH">Example 15-25</a>.</p>
<div class="example"><a id="BEICAHDH" name="BEICAHDH"></a><a id="TLADG367" name="TLADG367"></a>
<p><strong><em><font face="arial, helvetica, sans-serif">Example 15-25 XML Node with Self-Mapped Address Element</font></em></strong></p>
<pre xml:space="preserve" class="oac_no_warn">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;node&gt;
&lt;node name="first-name"&gt;Bob&lt;/node&gt;
&lt;node name="last-name"&gt;Smith&lt;/node&gt;
&lt;node name="street"&gt;123 A Street&lt;/node&gt;
&lt;node name="phone-number" type="work"&gt;555-1111&lt;/node&gt;
&lt;node name="phone-number" type="cell"&gt;555-2222&lt;/node&gt;
&lt;/node&gt;
</pre></div>
<!-- class="example" --></div>
<!-- class="sect2" --></div>
<!-- class="sect1" --></div>
<!-- class="ind" -->
<!-- Start Footer -->
<div class="footer">
<hr />
<table class="simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="100%">
<col width="33%" />
<col width="*" />
<col width="33%" />
<tr>
<td valign="bottom">
<table class="navigation simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="100" align="center">
<col width="*" />
<col width="48%" />
<col width="48%" />
<tr>
<td>&nbsp;</td>
<td align="center"><a href="jpatoxml004.htm"><img src="../../dcommon/images/larrow.png" alt="Previous" border="0" height="16" width="16" /></a></td>
<td align="center"><a href="jpatoxml006.htm"><img src="../../dcommon/images/rarrow.png" alt="Next" border="0" height="16" width="16" /></a></td>
</tr>
</table>
</td>
<td align="center" width="34%"><a href="http://www.eclipse.org/eclipselink/" title="EclipseLink home"><img src="../../dcommon/images/ellogo.png" alt="EclipseLink" width="150" border="0" /></a><br />
<font size="-2">Copyright&nbsp;&copy;&nbsp;2014,&nbsp;Oracle&nbsp;and/or&nbsp;its&nbsp;affiliates.&nbsp;All&nbsp;rights&nbsp;reserved.</font> <a href="../../dcommon/html/cpyr.htm"><br />
<td valign="bottom" align="right">
<table class="simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="225">
<tr>
<td>&nbsp;</td>
<td align="center" valign="top"><a href="toc.htm"><img src="../../dcommon/images/contents.png" alt="Go To Table Of Contents" border="0" height="16" width="16" /><br />
</td><td>&nbsp;</td><td align="center"><a href="../../" target="_top" class="external text" title="Search" rel="nofollow"><img src="../../dcommon/images/search.png" alt="Search" style="border:0;" /><br /><span class="mini"></span></a></td><td>&nbsp;</td><td align="center"><a href="../eclipselink_otlcg.pdf" title="PDF" target="_blank"><img src="../../dcommon/images/pdf_icon.png" style="padding-right:5px;border:0" alt="PDF"></a></td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<!-- class="footer" -->
<div id="copyright">Copyright &copy; 2014 by The Eclipse Foundation under the <a href="http://www.eclipse.org/org/documents/epl-v10.php">Eclipse Public License (EPL)</a><br /> <script type="text/javascript">var LastUpdated = document.lastModified;document.writeln ("Updated: " + LastUpdated);</script> </div><!-- START: Analytics --><script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-1608008-2']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script><!-- END: Analytics --><!-- START: Sharethis --><script>var options={ "publisher": "e2fe9e07-fab6-4f84-83ea-0991b429842c", "position": "right", "ad": { "visible": false, "openDelay": 5, "closeDelay": 0}};var st_hover_widget = new sharethis.widgets.hoverbuttons(options);</script><!-- END: Sharethis --></body>
</html>