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.
