Use Commons JXPath to select objects from a Collection
using predicates in XPath
expressions. The iterate( )
method on JXPathContext
takes an XPath expression and
returns an Iterator
that contains
each node satisfying that expression. The following example uses simple
XPath predicates to select Person
objects from a List
by age, first
name, and position:
import org.apache.commons.jxpath.JXPathContext; // Create a List of Person objects List people = new ArrayList( ); people.add(new Person("Ahmad", "Russell", 28 ); people.add(new Person("Tom", "Russell", 35 ); people.add(new Person("Ahmad", "Abuzayedeh", 33 ); // Select all people older than 30 System.out.println( "** People older than 30"); JXPathContext context = JXPathContext.newContext( people ); Iterator iterator = context.iterate(".[@age > 30]"); printPeople(iterator); // Select all people with a first name of 'Ahmad' context = JXPathContext.newContext( people ); System.out.println( "** People with first name 'Ahmad'" ); iterator = context.iterate(".[@firstName = 'Ahmad']"); printPeople(iterator); // Select the second person from the List context = JXPathContext.newContext( people ); System.out.println( "** Third Person in List" ); Person p = (Person) context.getValue(".[2]"); System.out.println( "Person: " + p.getFirstName( ) + " " + p.getLastName( ) + ", age: " + p.getAge( ) ); // A method to print out the result of each iteration. private void printPeople(Iterator iterator) { while( iterator.hasNext( ) ) { Person p = (Person) iterator.next( ); System.out.println( "Person: " + p.getFirstName( ) + " " + p.getLastName( ) + ", age: " + p.getAge( ) ); } }
A JXPathContext
is created by
passing a List
to newContext( )
, and each expression is
evaluated through a call to context.iterate()
. Three expressions are
evaluated, and the results of each expression are printed in the
printPeople( )
method:
** People older than 30 Person: Tom Russell, age: 35 Person: Ahmad Abuzayedeh, age: 33 ** People with first name 'Ahmad' Person: Ahmad Russell, age: 28 Person: Ahmad Abuzayedeh, age: 33 ** Second Person in List Person: Tom Russell, age: 35
The final expression in the previous example is a reference to a
specific index in a List
; .[2]
selected the second element in the
List
supplied to the JXPathContext
. Whenever an XPath expression deals with a property,
which is a List
or an array, a
one-based index can be supplied in brackets after the name of the
property. If a League
object contains
a List
of Team
objects, and a Team
object contains a List
of Player
objects, the third Player
object of the fourteenth Team
can be selected by using the XPath
expression league/teams[14]/players[3]
.
In the previous example, which filtered a List
of Person
objects, you might have noticed that
the properties age
and firstName
are referenced as attributes in the
XPath predicate expression. A property can be referenced either as an
element or an attribute. In XPath terms, when JXPath resolves properties
on an object, the child
and
attribute
axis both reference
properties. This means that the expressions .[@age > 30]
and .[age > 30]
would return the same results,
as age
can be addressed as a child
element or attribute of the current node.
iterate( )
returns an Iterator
that lets you iterate over all nodes
that satisfy the given XPath query. getValue(
)
returns the first matching result. In the previous example,
iterate( )
retrieves two Person
objects with an age
property greater than 30. If the same
expression were evaluated with getValue(
)
, only one Person
object
would have been returned: Tom Russell. Use iterate( )
when multiple nodes may match an
XPath expression.
Chapter 5 demonstrates the use
of Commons Collections'
CollectionUtils
to select items in a
Collection
that satisfy a Predicate
. For more information about using
Predicate
objects to filter
collections, refer to Recipe
5.4.