org.eclipse.persistence.oxm.annotations.XmlPath Maven / Gradle / Ivy
/*
* Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Matt MacIvor = 2.1 - Initial contribution
package org.eclipse.persistence.oxm.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* XPath based mapping is what allows an existing object model to be mapped
* to an existing XML schema. The {@literal @XmlPath} annotation is the means by
* which XPath based mapping is achieved.
*
* Example 1 - Using {@literal @XmlPath} to Add a Grouping Element
*
Sometimes grouping elements are added to your document to organise data. JAXB has this concept
* for collection properties in the form of {@linkplain jakarta.xml.bind.annotation.XmlElementWrapper}.
* Here we'll use {@literal @XmlPath} for non-collection properties.
* In this case we'll nest the billing/shipping address data within the "contact-info" element.
* {@snippet :
* import jakarta.xml.bind.annotation.*;
* import org.eclipse.persistence.oxm.annotations.XmlPath;
*
* @XmlRootElement
* @XmlAccessorType(XmlAccessType.FIELD)
* public class Customer {
* @XmlPath("contact-info/billing-address")
* private Address billingAddress;
*
* @XmlPath("contact-info/shipping-address")
* private Address shippingAddress;
* }
* }
* This will produce XML like:
* {@snippet lang="XML":
*
*
*
*
* 1 Billing Street
*
*
* 2 Shipping Road
*
*
*
*
* }
*
* Example 2 - Using {@literal @XmlPath} to Map by Position
*
Normally in JAXB elements with the same name must be mapped to a collection property.
* Using the {@literal @XmlPath} extension you map non-collection properties to a repeated element by index.
* {@snippet :
* import jakarta.xml.bind.annotation.*;
* import org.eclipse.persistence.oxm.annotations.XmlPath;
*
* @XmlRootElement
* @XmlAccessorType(XmlAccessType.FIELD)
* public class Customer {
* @XmlPath("address[1]")
* private Address billingAddress;
*
* @XmlPath("address[2]")
* private Address shippingAddress;
* }
* }
* This will produce XML like:
* {@snippet lang="XML":
*
*
*
* 1 Billing Street
*
*
* 2 Shipping Road
*
*
*
* }
*
* Example 3 - Using {@literal @XmlPath} to Map Two Objects to the Same Node
*
We have seen how {@literal @XmlPath} can be used to expand the structure by adding a grouping element.
* {@literal @XmlPath} can also be used to collapse the structure by mapping two objects to the same node.
* {@snippet :
* import jakarta.xml.bind.annotation.*;
* import org.eclipse.persistence.oxm.annotations.XmlPath;
*
* @XmlRootElement
* @XmlAccessorType(XmlAccessType.FIELD)
* public class Customer {
* @XmlPath(".")
* private Address billingAddress;
*
* private Address shippingAddress;
* }
* }
* This will produce XML like:
* {@snippet lang="XML":
*
*
* 1 Billing Street
*
* 2 Shipping Road
*
*
*
* }
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(XmlPaths.class)
public @interface XmlPath {
/**
* The XPath for this property. A subset of the XPath specification may be
* used to specify mappings. The following concepts are supported:
*
* - Attribute - "@id"
* - Element - "address"
* - Element by Position - "address[1]"
* - Element by Predicate - "address[@type='mailing']"
* - Element Text - "name/text()"
* - Text - "text()"
* - Self - "."
* - Combination - "personal-info/name[2]/text()"
*
* For namespace qualified nodes, the prefixes defined in the {@linkplain jakarta.xml.bind.annotation.XmlNs}
* annotations can be used to qualify the XPath fragments. Unqualified
* fragments will assumed to be in the namespace specified using
* {@linkplain jakarta.xml.bind.annotation.XmlSchema}.
* Example:
*
Assuming the following namespace information has been set up using the
* {@linkplain jakarta.xml.bind.annotation.XmlSchema} annotation:
* {@snippet :
* @XmlSchema(namespace = "https://www.example.org/FOO",
* xmlns = {@XmlNs(prefix="ns", namespaceURI="https://www.example.com/BAR")},
* elementFormDefault = XmlNsForm.QUALIFIED)
* package org.example;
*
* import jakarta.xml.bind.annotation.*;
* }
* Then the following XPath:
* {@snippet :
* @XmlPath("contact-info/ns:address/@id")
* }
* Will be qualified as:
*
* - contact-info - in "https://www.example.org/FOO" namespace.
* - address - in "https://www.example.com/BAR" namespace.
* - @id - in no namespace.
*
* @see jakarta.xml.bind.annotation.XmlSchema
* @see jakarta.xml.bind.annotation.XmlNs
*/
String value();
}