details how to bind Java interfaces to XML documents using XPath expressions.

XPath Expressions

Let us look at the XML example document from the Getting Started guide. File book.xml is:

<book title="Treasure Island">
   <reference url="http://en.wikipedia.org/wiki/Treasure_Island" lang="en"/>
   <reference url="http://fr.wikipedia.org/wiki/L'Île_au_trésor" lang="fr"/>
   <publishedIn>1883</publishedIn>
   <author>
       <name>Robert Louis Stevenson</name>
       <name>R. L. Stevenson</name>            
   </author>
</book>

Every valid XPath expression can be declared in the clazz interface through the @XPath annotation.

For instance, for the clazz interface itself, the following XPath expressions are equivalent:

  • @XPath("/book")
  • @XPath("/*")
  • @XPath("/*[name() = 'book']")
  • @XPath("/*/*/..")
  • @XPath("/*/child:*/parent:book")
  • etc.

Here are some examples of XPath annotations suitable for methods:

  • @XPath("@title")
  • @XPath("publishedIn")
  • @XPath("author/people")
  • @XPath("reference")
  • @XPath("@*[. = 'Treasure Island']")
  • @XPath("publishedIn[../author/name = 'Robert Louis Stevenson']")
  • etc.

XPath Functions

Sometimes you wish to process the DOM nodes selected by the XPath expression.

For instance, from our book.xml file, say you want to select the publication date's century instead of the whole year. You would use the @XPath annotation like this:

package aaa.bbb.ccc;

import net.avcompris.binding.annotation.XPath;

@XPath("/book") 
public interface Book {

    @XPath(value = "publishedIn", function = "floor(. div 100) + 1") 
    int getPublicationCentury();

    ...
}

The function @XPath annotation's parameter allows you to declare an XPath function which the DomBinder will run on each node selected by the XPath expression.

Of course we will have:

...

import static org.junit.Assert.assertEquals;

        ...

        assertEquals(19, book.getPublicationCentury());

        ...

Note: The XPath expression is passed via a parameter named value — that is, not expression — for convenience: You can omit "value=..." when no function parameter is given

XPath fail-function

When the XPath processor encounters a "no node" situation, for instance when an element has no child, the function execution will crash. In that case it is convenient to have a fail-function that will return a default value.

For instance, the following function will crash in situations where there is no mytag node at all:

    @XPath(value = "mytag", function = "count(child:*)") 
    int getCountBelowMyTag();

The solution is to provide a fail-function with a default value:

    @XPath(value = "mytag", function = "count(child:*)", failFunction = "0") 
    int getCountBelowMyTag();

More details are shown in the Return Types page.

XPath Variables

From version 0.0.3-SNAPSHOT, you can use variables in your XPath expressions.

For instance:

    @XPath("//reference[@lang = $arg0]/@url")
    String getReferenceUrlByLang(String s)

And use it like this:

    assertEquals("http://en.wikipedia.org/wiki/Treasure_Island",
        book.getReferenceUrlByLang("en"));

    assertEquals("http://fr.wikipedia.org/wiki/L'Île_au_trésor",
        book.getReferenceUrlByLang("fr"));

The following variable names are recognized:

  • $arg0, $arg1, $arg2… — the arguments passed to the method during the call.
  • $methodName — the name of the Java method which is invoked.

BindConfiguration.setXPathXxx()

Alternatively to the @XPath annotation, you can use a BindConfiguration object that will hold XPath declarations. This is convenient when your clazz interface was not annotated at first.

Use of a BindConfiguration parameter overrides any @XPath annotation.

Syntax is the same as with the @XPath annotation.