Use Jakarta 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.
18.217.150.123