A specialized implementation of the
ExpressionEngine interface that
is able to evaluate XPATH expressions.
This class makes use of Commons
JXPath for handling XPath expressions and mapping them to the nodes of a
hierarchical configuration. This makes the rich and powerful XPATH syntax
available for accessing properties from a configuration object.
For selecting properties arbitrary XPATH expressions can be used, which
select single or multiple configuration nodes. The associated
Configuration instance will directly pass the specified property keys
into this engine. If a key is not syntactically correct, an exception will be
thrown.
For adding new properties, this expression engine uses a specific syntax: the
"key" of a new property must consist of two parts that are
separated by whitespace:
- An XPATH expression selecting a single node, to which the new element(s)
are to be added. This can be an arbitrary complex expression, but it must
select exactly one node, otherwise an exception will be thrown.
- The name of the new element(s) to be added below this parent node. Here
either a single node name or a complete path of nodes (separated by the
"/" character or "@" for an attribute) can be specified.
Some examples for valid keys that can be passed into the configuration's
addProperty() method follow:
"/tables/table[1] type"
This will add a new
type node as a child of the first
tableelement.
"/tables/table[1] @type"
Similar to the example above, but this time a new attribute named
type will be added to the first
table element.
"/tables table/fields/field/name"
This example shows how a complex path can be added. Parent node is the
tables element. Here a new branch consisting of the nodes
table,
fields,
field, and
name will be added.
"/tables table/fields/field@type"
This is similar to the last example, but in this case a complex path ending
with an attribute is defined.
Note: This extended syntax for adding properties only works
with the
addProperty() method.
setProperty() does not support
creating new nodes this way.
From version 1.7 on, it is possible to use regular keys in calls to
addProperty() (i.e. keys that do not have to contain a whitespace as
delimiter). In this case the key is evaluated, and the biggest part pointing
to an existing node is determined. The remaining part is then added as new
path. As an example consider the key
"tables/table[last()]/fields/field/name"
If the key does not point to an existing node, the engine will check the
paths
"tables/table[last()]/fields/field",
"tables/table[last()]/fields",
"tables/table[last()]", and so
on, until a key is found which points to a node. Let's assume that the last
key listed above can be resolved in this way. Then from this key the
following key is derived:
"tables/table[last()] fields/field/name" by
appending the remaining part after a whitespace. This key can now be
processed using the original algorithm. Keys of this form can also be used
with the
setProperty() method. However, it is still recommended to
use the old format because it makes explicit at which position new nodes
should be added. For keys without a whitespace delimiter there may be
ambiguities.