}
// We now know that we are dealing with 'simple' XPaths. However,
// we don't cater for functions besides the text() function, so if we
// find a '(' we need to determine whether the function is text or not.
ODOMObservable odomObservable = null;
StringTokenizer tokenizer = new StringTokenizer(xpathStr, XPATH_DELIM);
// Create an XPath relative to the parent (tracked during path
// traversal). For example, with a context of 'a' and an XPath of
// 'b/c/d' the parent and relative XPath will change as follows for
// each token found:
//
// Parent XPath Token
// ------ ----- -----
// a b b
// a/b c c
// a/b/c d d
Element parent = context;
XPath xpath;
String xPathToken;
while (tokenizer.hasMoreTokens()) {
xPathToken = tokenizer.nextToken();
// @todo pass the namespaces on in a nicer way (e.g. have a protected constructor that takes the map and copies it)
xpath = new XPath(xPathToken, this.getNamespacesString());
// Check to see if the node or nodes already exist in the document.
List nodes = xpath.selectNodes(parent);
ODOMObservable node = null;
if ((nodes == null) || (nodes.size() == 0)) {
// Node wasn't found, so create one.
ODOMObservable result = null;
int predicateStart = xPathToken.indexOf(PREDICATE_START);
// Handle a predicate on the current path step if needed
if (predicateStart != -1) {
String predicate =