summaryrefslogtreecommitdiffstats
path: root/axiom/src/xpath
diff options
context:
space:
mode:
Diffstat (limited to 'axiom/src/xpath')
-rw-r--r--axiom/src/xpath/Makefile.am22
-rwxr-xr-xaxiom/src/xpath/xpath.c462
-rwxr-xr-xaxiom/src/xpath/xpath_functions.c46
-rwxr-xr-xaxiom/src/xpath/xpath_functions.h47
-rwxr-xr-xaxiom/src/xpath/xpath_internals.c38
-rwxr-xr-xaxiom/src/xpath/xpath_internals.h199
-rw-r--r--axiom/src/xpath/xpath_internals_engine.c1203
-rwxr-xr-xaxiom/src/xpath/xpath_internals_engine.h265
-rw-r--r--axiom/src/xpath/xpath_internals_iterators.c588
-rwxr-xr-xaxiom/src/xpath/xpath_internals_iterators.h298
-rwxr-xr-xaxiom/src/xpath/xpath_internals_parser.c1245
-rwxr-xr-xaxiom/src/xpath/xpath_internals_parser.h421
-rwxr-xr-xaxiom/src/xpath/xpath_streaming.c213
-rwxr-xr-xaxiom/src/xpath/xpath_streaming.h126
14 files changed, 5173 insertions, 0 deletions
diff --git a/axiom/src/xpath/Makefile.am b/axiom/src/xpath/Makefile.am
new file mode 100644
index 0000000..5d4f42f
--- /dev/null
+++ b/axiom/src/xpath/Makefile.am
@@ -0,0 +1,22 @@
+lib_LTLIBRARIES = libaxis2_xpath.la
+libaxis2_xpath_la_SOURCES = xpath.c \
+ xpath_functions.c \
+ xpath_internals.c \
+ xpath_internals_engine.c \
+ xpath_internals_iterators.c \
+ xpath_internals_parser.c \
+ xpath_streaming.c
+
+libaxis2_xpath_la_LDFLAGS = -version-info $(VERSION_NO)
+
+libaxis2_xpath_la_LIBADD =
+INCLUDES = -I$(top_builddir)/include \
+ -I$(top_builddir)/src/parser \
+ -I$(top_builddir)/src/om \
+ -I ../../../util/include \
+ -I ../../../include
+
+EXTRA_DIST = xpath_functions.h xpath_internals_engine.h \
+ xpath_internals.h xpath_internals_iterators.h \
+ xpath_internals_parser.h xpath_streaming.h
+
diff --git a/axiom/src/xpath/xpath.c b/axiom/src/xpath/xpath.c
new file mode 100755
index 0000000..38f422c
--- /dev/null
+++ b/axiom/src/xpath/xpath.c
@@ -0,0 +1,462 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <axiom_xpath.h>
+#include "xpath_internals.h"
+#include "xpath_internals_parser.h"
+#include "xpath_internals_engine.h"
+#include "xpath_functions.h"
+#include "xpath_streaming.h"
+
+/* Create XPath context */
+AXIS2_EXTERN axiom_xpath_context_t * AXIS2_CALL
+axiom_xpath_context_create(
+ const axutil_env_t *env,
+ axiom_node_t * root_node)
+{
+ axiom_xpath_context_t* context;
+
+ /*HACK: xpath impl requires a dummy root node in order to process properly.*/
+ axiom_node_t * dummy_root;
+ dummy_root = axiom_node_create(env);
+ axiom_node_add_child(dummy_root, env, root_node);
+
+ context = AXIS2_MALLOC(env->allocator,
+ sizeof(axiom_xpath_context_t));
+
+ context->env = env;
+ context->root_node = dummy_root;
+ context->node = dummy_root;
+ context->expr = NULL;
+ context->attribute = NULL;
+ context->namespaces = NULL;
+ context->functions = NULL;
+
+ axiom_xpath_register_default_functions_set(context);
+
+ return context;
+}
+
+/* Compile XPath expression */
+AXIS2_EXTERN axiom_xpath_expression_t * AXIS2_CALL
+axiom_xpath_compile_expression(
+ const axutil_env_t *env,
+ const axis2_char_t* xpath_expr)
+{
+ axiom_xpath_expression_t* expr;
+
+ expr = AXIS2_MALLOC(env->allocator,
+ sizeof(axiom_xpath_expression_t));
+
+ expr->expr_str = axutil_strdup(env, xpath_expr);
+
+ if (axiom_xpath_compile(env, expr) == AXIOM_XPATH_PARSE_ERROR)
+ {
+ AXIS2_FREE(env->allocator, expr->expr_str);
+ AXIS2_FREE(env->allocator, expr);
+
+ return NULL;
+ }
+ else
+ {
+ return expr;
+ }
+}
+
+/* Evaluate compiled XPath expression */
+AXIS2_EXTERN axiom_xpath_result_t * AXIS2_CALL
+axiom_xpath_evaluate(
+ axiom_xpath_context_t *context,
+ axiom_xpath_expression_t *xpath_expr)
+{
+ axiom_xpath_expression_copy(context, xpath_expr);
+
+ context->streaming = AXIS2_FALSE;
+
+ return axiom_xpath_run(context);
+}
+
+AXIS2_EXTERN axiom_xpath_result_t * AXIS2_CALL
+axiom_xpath_evaluate_streaming(
+ axiom_xpath_context_t *context,
+ axiom_xpath_expression_t *xpath_expr)
+{
+ axiom_xpath_result_t *res;
+
+ axiom_xpath_expression_copy(context, xpath_expr);
+
+ if (axiom_xpath_streaming_check(context->env, xpath_expr))
+ {
+ context->streaming = AXIS2_TRUE;
+ return axiom_xpath_run(context);
+ }
+ else
+ {
+ res = AXIS2_MALLOC(
+ context->env->allocator, sizeof(axiom_xpath_result_t));
+ res->nodes = NULL;
+ res->flag = AXIOM_XPATH_ERROR_STREAMING_NOT_SUPPORTED;
+
+ return res;
+ }
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_xpath_register_default_functions_set(
+ axiom_xpath_context_t *context)
+{
+ axiom_xpath_register_function(
+ context, "count", axiom_xpath_function_count);
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_xpath_register_function(
+ axiom_xpath_context_t *context,
+ axis2_char_t *name,
+ axiom_xpath_function_t func)
+{
+ if (name && func)
+ {
+ if (!context->functions)
+ {
+ context->functions = axutil_hash_make(context->env);
+ }
+
+ axutil_hash_set(context->functions, name, AXIS2_HASH_KEY_STRING, func);
+ }
+}
+
+AXIS2_EXTERN axiom_xpath_function_t AXIS2_CALL
+axiom_xpath_get_function(
+ axiom_xpath_context_t *context,
+ axis2_char_t *name)
+{
+ axiom_xpath_function_t func = NULL;
+
+ if(context->functions)
+ {
+ func = axutil_hash_get(context->functions, name, AXIS2_HASH_KEY_STRING);
+ }
+
+ return func;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_xpath_register_namespace(
+ axiom_xpath_context_t *context,
+ axiom_namespace_t *ns)
+{
+ axis2_char_t *prefix = NULL;
+
+ if (!context->namespaces)
+ {
+ context->namespaces = axutil_hash_make(context->env);
+ }
+
+ prefix = axiom_namespace_get_prefix(ns, context->env);
+
+ if (prefix)
+ {
+ axutil_hash_set(
+ context->namespaces, prefix, AXIS2_HASH_KEY_STRING, ns);
+ }
+}
+
+AXIS2_EXTERN axiom_namespace_t * AXIS2_CALL
+axiom_xpath_get_namespace(
+ axiom_xpath_context_t *context,
+ axis2_char_t *prefix)
+{
+ axiom_namespace_t *ns = NULL;
+
+ if (context->namespaces)
+ {
+ ns = axutil_hash_get(context->namespaces, prefix, AXIS2_HASH_KEY_STRING);
+ }
+
+ return ns;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_xpath_clear_namespaces(
+ axiom_xpath_context_t *context)
+{
+ axutil_hash_index_t *hi;
+ void *val;
+
+ if (context->namespaces)
+ {
+ for (hi = axutil_hash_first(context->namespaces, context->env);
+ hi;
+ hi = axutil_hash_next(context->env, hi))
+ {
+ axutil_hash_this(hi, NULL, NULL, &val);
+ axiom_namespace_free((axiom_namespace_t *)val, context->env);
+ }
+
+ axutil_hash_free(context->namespaces, context->env);
+ }
+
+ context->namespaces = NULL;
+}
+
+/* Cast to boolean */
+AXIS2_EXTERN axis2_bool_t AXIS2_CALL
+axiom_xpath_cast_node_to_boolean(
+ const axutil_env_t *env,
+ axiom_xpath_result_node_t * node)
+{
+ if(node->type == AXIOM_XPATH_TYPE_BOOLEAN)
+ {
+ return *(axis2_bool_t *)node->value;
+ }
+ else if(node->type == AXIOM_XPATH_TYPE_NUMBER)
+ {
+ /* Cannot evaluate as *(double *)(node->value) == 1e-12
+ since there might be an precision error */
+ if(*(double *)(node->value) > 1e-12 || *(double *)(node->value) < -1e-12)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ else if(node->value)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+}
+
+/* Cast to double */
+AXIS2_EXTERN double AXIS2_CALL
+axiom_xpath_cast_node_to_number(
+ const axutil_env_t *env,
+ axiom_xpath_result_node_t * node)
+{
+ if (node->type == AXIOM_XPATH_TYPE_BOOLEAN)
+ {
+ if (*(axis2_bool_t *)(node->value) == AXIS2_TRUE)
+ {
+ return 1.0;
+ }
+ else
+ {
+ return 0.0;
+ }
+ }
+ else if (node->type == AXIOM_XPATH_TYPE_NUMBER)
+ {
+ return *(double *)node->value;
+ }
+ else if (node->value)
+ {
+ return 1.0;
+ }
+ else
+ {
+ return 0.0;
+ }
+}
+
+/* Cast to text */
+AXIS2_EXTERN axis2_char_t * AXIS2_CALL
+axiom_xpath_cast_node_to_string(
+ const axutil_env_t *env,
+ axiom_xpath_result_node_t * node)
+{
+ axiom_element_t *ele;
+ axis2_char_t *res;
+
+ if (!node->value)
+ {
+ return NULL;
+ }
+
+ if (node->type == AXIOM_XPATH_TYPE_BOOLEAN)
+ {
+ if (*(axis2_bool_t *)(node->value) == AXIS2_TRUE)
+ {
+ return axutil_strdup(env, "true");
+ }
+ else
+ {
+ return axutil_strdup(env, "false");
+ }
+ }
+ else if (node->type == AXIOM_XPATH_TYPE_NUMBER)
+ {
+ /* Allocate 50 bytes */
+ res = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * 50);
+
+ sprintf(res, "%lf", *(double *)(node->value));
+
+ return res;
+ }
+ else if (node->type == AXIOM_XPATH_TYPE_TEXT)
+ {
+ return (axis2_char_t *)node->value;
+ }
+ else if (node->type == AXIOM_XPATH_TYPE_NODE)
+ {
+ ele = (axiom_element_t *)axiom_node_get_data_element(
+ (axiom_node_t *)(node->value), env);
+
+ if (ele)
+ {
+ return axiom_element_get_text(
+ ele, env, (axiom_node_t *)(node->value));
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ else if (node->type == AXIOM_XPATH_TYPE_ATTRIBUTE)
+ {
+ return axiom_attribute_get_value(
+ (axiom_attribute_t *)(node->value), env);
+ }
+ else if (node->type == AXIOM_XPATH_TYPE_NAMESPACE)
+ {
+ return axiom_namespace_get_prefix(
+ (axiom_namespace_t *)(node->value), env);
+ }
+
+ return NULL;
+}
+
+/* Cast to axiom node */
+AXIS2_EXTERN axiom_node_t * AXIS2_CALL
+axiom_xpath_cast_node2axiom_node(
+ const axutil_env_t *env,
+ axiom_xpath_result_node_t * node)
+{
+ if (node->type == AXIOM_XPATH_TYPE_NODE && node->value)
+ {
+ return (axiom_node_t *)node->value;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+/* Free context */
+AXIS2_EXTERN void AXIS2_CALL
+axiom_xpath_free_context(
+ const axutil_env_t *env,
+ axiom_xpath_context_t *context)
+{
+ if (context)
+ {
+ /* Free the expression if not freed */
+ if (context->expr)
+ {
+ /* axiom_xpath_free_expression(env, context->expr); */
+
+ context->expr = NULL;
+ }
+
+ if (context->root_node)
+ {
+ axiom_node_detach(axiom_node_get_first_child(context->root_node, context->env), context->env);
+ axiom_node_free_tree(context->root_node, context->env);
+ context->root_node = NULL;
+ }
+
+ if (context->functions)
+ {
+ axutil_hash_free(context->functions, context->env);
+ context->functions = NULL;
+ }
+
+ if(context->namespaces)
+ {
+ axiom_xpath_clear_namespaces(context);
+ context->namespaces = NULL;
+ }
+
+ AXIS2_FREE(env->allocator, context);
+ }
+}
+
+/* Free expression */
+AXIS2_EXTERN void AXIS2_CALL
+axiom_xpath_free_expression(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t * xpath_expr)
+{
+ if (xpath_expr)
+ {
+ if (xpath_expr->expr_str)
+ {
+ AXIS2_FREE(env->allocator, xpath_expr->expr_str);
+
+ xpath_expr->expr_str = NULL;
+ }
+
+ if (xpath_expr->operations)
+ {
+ axutil_array_list_free(xpath_expr->operations, env);
+ xpath_expr->operations = NULL;
+ }
+
+ AXIS2_FREE(env->allocator, xpath_expr);
+ }
+}
+
+/* Free result set */
+AXIS2_EXTERN void AXIS2_CALL
+axiom_xpath_free_result(
+ const axutil_env_t *env,
+ axiom_xpath_result_t* result)
+{
+ if (result)
+ {
+ if (result->nodes)
+ {
+ axutil_array_list_free(result->nodes, env);
+ }
+
+ AXIS2_FREE(env->allocator, result);
+ }
+}
+
+/* Check if the expression can be evaluated on streaming XML */
+AXIS2_EXTERN axis2_bool_t AXIS2_CALL
+axiom_xpath_streaming_check(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ axiom_xpath_streaming_t r = AXIOM_XPATH_CHECK(expr->start);
+
+ if(r == AXIOM_XPATH_STREAMING_NOT_SUPPORTED)
+ {
+ return AXIS2_FALSE;
+ }
+ else
+ {
+ return AXIS2_TRUE;
+ }
+}
+
diff --git a/axiom/src/xpath/xpath_functions.c b/axiom/src/xpath/xpath_functions.c
new file mode 100755
index 0000000..bdf65c2
--- /dev/null
+++ b/axiom/src/xpath/xpath_functions.c
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <axiom_xpath.h>
+#include "xpath_functions.h"
+#include "xpath_internals_engine.h"
+
+int
+axiom_xpath_function_count(
+ axiom_xpath_context_t *context,
+ int np)
+{
+ axiom_xpath_result_node_t *node;
+ double * v;
+ int i;
+
+ node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t));
+ v = AXIS2_MALLOC(context->env->allocator, sizeof(double));
+
+ *v = np;
+ node->value = v;
+ node->type = AXIOM_XPATH_TYPE_NUMBER;
+
+ for(i = 0; i < np; i++)
+ {
+ axutil_stack_pop(context->stack, context->env);
+ }
+
+ axutil_stack_push(context->stack, context->env, node);
+
+ return 1;
+}
diff --git a/axiom/src/xpath/xpath_functions.h b/axiom/src/xpath/xpath_functions.h
new file mode 100755
index 0000000..d44f0a2
--- /dev/null
+++ b/axiom/src/xpath/xpath_functions.h
@@ -0,0 +1,47 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AXIOM_XPATH_FUNCTIONS_H
+#define AXIOM_XPATH_FUNCTIONS_H
+
+#include <axiom_xpath.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /**
+ * @defgroup axiom_xpath_functions functions
+ * @ingroup axiom_xpath
+ * @{
+ */
+
+ /**
+ * count(node-set) function
+ * http://www.w3.org/TR/xpath#function-count
+ */
+ int axiom_xpath_function_count(axiom_xpath_context_t *context, int np);
+
+ /** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/axiom/src/xpath/xpath_internals.c b/axiom/src/xpath/xpath_internals.c
new file mode 100755
index 0000000..c313baf
--- /dev/null
+++ b/axiom/src/xpath/xpath_internals.c
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <axiom_xpath.h>
+#include "xpath_internals.h"
+
+/* Make a copy of the xpath expression */
+void
+axiom_xpath_expression_copy(
+ axiom_xpath_context_t *context,
+ axiom_xpath_expression_t* expr)
+{
+ int i;
+ axiom_xpath_operation_t *op;
+
+ context->expr = expr;
+
+ /* Set value of pos in every operation to 0 */
+ for(i = 0; i < axutil_array_list_size(expr->operations, context->env); i++)
+ {
+ op = AXIOM_XPATH_OPR_GET(i);
+ op->pos = 0;
+ }
+}
diff --git a/axiom/src/xpath/xpath_internals.h b/axiom/src/xpath/xpath_internals.h
new file mode 100755
index 0000000..891d543
--- /dev/null
+++ b/axiom/src/xpath/xpath_internals.h
@@ -0,0 +1,199 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AXIOM_XPATH_INTERNALS_H
+#define AXIOM_XPATH_INTERNALS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /**
+ * @defgroup axiom_xpath_internals internals
+ * @ingroup axiom_xpath
+ * @{
+ */
+
+
+ /** Get operation at index ind */
+#define AXIOM_XPATH_OPR_GET(ind) (axiom_xpath_operation_t *) \
+ axutil_array_list_get(context->expr->operations, context->env, ind)
+
+ /**
+ * An error has occured while parsing
+ */
+#define AXIOM_XPATH_PARSE_ERROR -2
+
+ /**
+ * XPath expression was successfully compiled
+ */
+#define AXIOM_XPATH_PARSE_SUCCESS 0
+
+ /**
+ * End of expression reached
+ */
+#define AXIOM_XPATH_PARSE_END -1
+
+ /* Types */
+
+ /**
+ * XPath operation
+ * Contains the operands and parameters
+ */
+ typedef struct axiom_xpath_operation axiom_xpath_operation_t;
+
+ /**
+ * XPath node test
+ * Stores the components of a node test
+ */
+ typedef struct axiom_xpath_node_test axiom_xpath_node_test_t;
+
+ /**
+ * Functions to process a XPath operator
+ */
+ typedef int (*axiom_xpath_operator_t)(axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op);
+
+ /**
+ * Functions to iterate through different XPath axes
+ */
+ typedef int (*axiom_xpath_iterator_t)(axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * XPath node test types
+ */
+ typedef enum axiom_xpath_node_test_type_t
+ {
+ AXIOM_XPATH_NODE_TEST_NONE = 0,
+ AXIOM_XPATH_NODE_TEST_ALL,
+ AXIOM_XPATH_NODE_TYPE_COMMENT,
+ AXIOM_XPATH_NODE_TYPE_NODE,
+ AXIOM_XPATH_NODE_TYPE_PI,
+ AXIOM_XPATH_NODE_TYPE_TEXT,
+ AXIOM_XPATH_NODE_TEST_STANDARD
+ } axiom_xpath_node_test_type_t;
+
+ /**
+ * XPath operations
+ */
+ typedef enum axiom_xpath_operation_type_t
+ {
+ AXIOM_XPATH_OPERATION_ROOT_NODE = 0,
+ AXIOM_XPATH_OPERATION_CONTEXT_NODE,
+ AXIOM_XPATH_OPERATION_NODE_TEST,
+ AXIOM_XPATH_OPERATION_STEP,
+ AXIOM_XPATH_OPERATION_RESULT,
+ AXIOM_XPATH_OPERATION_UNION,
+ AXIOM_XPATH_OPERATION_EQUAL_EXPR,
+ AXIOM_XPATH_OPERATION_AND_EXPR,
+ AXIOM_XPATH_OPERATION_OR_EXPR,
+ AXIOM_XPATH_OPERATION_PREDICATE,
+ AXIOM_XPATH_OPERATION_LITERAL,
+ AXIOM_XPATH_OPERATION_NUMBER,
+ AXIOM_XPATH_OPERATION_PATH_EXPRESSION,
+ AXIOM_XPATH_OPERATION_FUNCTION_CALL,
+ AXIOM_XPATH_OPERATION_ARGUMENT
+ } axiom_xpath_operation_type_t;
+
+ /**
+ * XPath axes
+ */
+ typedef enum axiom_xpath_axis_t
+ {
+ AXIOM_XPATH_AXIS_NONE = -1,
+ AXIOM_XPATH_AXIS_CHILD,
+ AXIOM_XPATH_AXIS_DESCENDANT,
+ AXIOM_XPATH_AXIS_PARENT,
+ AXIOM_XPATH_AXIS_ANCESTOR,
+ AXIOM_XPATH_AXIS_FOLLOWING_SIBLING,
+ AXIOM_XPATH_AXIS_PRECEDING_SIBLING,
+ AXIOM_XPATH_AXIS_FOLLOWING,
+ AXIOM_XPATH_AXIS_PRECEDING,
+ AXIOM_XPATH_AXIS_ATTRIBUTE,
+ AXIOM_XPATH_AXIS_NAMESPACE,
+ AXIOM_XPATH_AXIS_SELF,
+ AXIOM_XPATH_AXIS_DESCENDANT_OR_SELF,
+ AXIOM_XPATH_AXIS_ANCESTOR_OR_SELF
+ } axiom_xpath_axis_t;
+
+ /**
+ * XPath node test structure
+ */
+ struct axiom_xpath_node_test
+ {
+ /** Node test type */
+ axiom_xpath_node_test_type_t type;
+
+ /** Prefix
+ * NULL if no prefix
+ */
+ axis2_char_t *prefix;
+
+ /** Name */
+ axis2_char_t *name;
+
+ /** Literal for processing instruction (PI) */
+ axis2_char_t *lit;
+ };
+
+ /**
+ * XPath operation structure
+ */
+ struct axiom_xpath_operation
+ {
+ /** Type of operator */
+ axiom_xpath_operation_type_t opr;
+
+ /** Parameters of the operation */
+ void *par1;
+ void *par2;
+
+ /** Position: Used for predicate evaluation
+ */
+ int pos;
+
+ /** Operands pointing to other operations */
+ int op1;
+ int op2;
+ };
+
+ /**
+ * Copies an XPath expression to a context
+ *
+ * No data is duplicated just the reference is assigned.
+ * Some parameters in the expression are reset.
+ * - pos in every operation
+ *
+ * @param context XPath context must not be NULL
+ * @param expr Expression to be copied
+ */
+ void axiom_xpath_expression_copy(
+ axiom_xpath_context_t *context,
+ axiom_xpath_expression_t* expr);
+
+ /** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/axiom/src/xpath/xpath_internals_engine.c b/axiom/src/xpath/xpath_internals_engine.c
new file mode 100644
index 0000000..3c96d0e
--- /dev/null
+++ b/axiom/src/xpath/xpath_internals_engine.c
@@ -0,0 +1,1203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <axiom_xpath.h>
+#include "xpath_internals.h"
+#include "xpath_internals_engine.h"
+#include "xpath_internals_iterators.h"
+
+/* Evaluates the expath expression */
+axiom_xpath_result_t *
+axiom_xpath_run(
+ axiom_xpath_context_t *context)
+{
+ axiom_xpath_result_t* res;
+
+ /* Initialize result ret */
+ res = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_t));
+
+ res->flag = 0;
+
+ res->nodes = axutil_array_list_create(context->env, 0);
+
+ /* Expression is empty */
+ if(context->expr->start == AXIOM_XPATH_PARSE_END)
+ {
+ return res;
+ }
+
+ context->stack = axutil_stack_create(context->env);
+
+ axiom_xpath_evaluate_operation(context, context->expr->start);
+
+ /* Add nodes to the result set from the stack */
+ while(axutil_stack_size(context->stack, context->env) > 0)
+ {
+ axutil_array_list_add(res->nodes, context->env,
+ axutil_stack_pop(context->stack, context->env));
+ }
+
+ axutil_stack_free(context->stack, context->env);
+
+ return res;
+}
+
+/* Casting functions; these make use of the casting functions defined in xpath.h */
+void
+axiom_xpath_cast_boolean(
+ axiom_xpath_result_node_t *node,
+ axiom_xpath_context_t *context)
+{
+ axis2_bool_t v = axiom_xpath_cast_node_to_boolean(context->env, node);
+
+ AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, v);
+
+ node->type = AXIOM_XPATH_TYPE_BOOLEAN;
+}
+
+void
+axiom_xpath_cast_number(
+ axiom_xpath_result_node_t *node,
+ axiom_xpath_context_t *context)
+{
+ double v = axiom_xpath_cast_node_to_number(context->env, node);
+
+ AXIOM_XPATH_CAST_SET_VALUE(double, v);
+
+ node->type = AXIOM_XPATH_TYPE_NUMBER;
+}
+
+void
+axiom_xpath_cast_string(
+ axiom_xpath_result_node_t *node,
+ axiom_xpath_context_t *context)
+{
+ node->value = axiom_xpath_cast_node_to_string(context->env, node);
+
+ node->type = AXIOM_XPATH_TYPE_TEXT;
+}
+
+/* Evaluate whether two results are equal
+
+ If either node is a boolean other is casted to a boolean;
+ Otherwise, if either node is a number other is casted to a number;
+ Otherwise, both nodes are casted to strings.*/
+axis2_bool_t
+axiom_xpath_compare_equal(
+ axiom_xpath_result_node_t *node1,
+ axiom_xpath_result_node_t *node2,
+ axiom_xpath_context_t *context)
+{
+ if(node1->type == AXIOM_XPATH_TYPE_BOOLEAN || node2->type == AXIOM_XPATH_TYPE_BOOLEAN)
+ {
+ axiom_xpath_cast_boolean(node1, context);
+ axiom_xpath_cast_boolean(node2, context);
+
+ if(*(axis2_bool_t*)(node1->value) == *(axis2_bool_t*)(node2->value))
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+ }
+
+ if(node1->type == AXIOM_XPATH_TYPE_NUMBER || node2->type == AXIOM_XPATH_TYPE_NUMBER)
+ {
+ axiom_xpath_cast_number(node1, context);
+ axiom_xpath_cast_number(node2, context);
+
+ if(*(double *)(node1->value) == *(double *)(node2->value))
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+ }
+
+ axiom_xpath_cast_string(node1, context);
+ axiom_xpath_cast_string(node2, context);
+
+ if(axutil_strcmp((axis2_char_t *)(node1->value), (axis2_char_t *)(node2->value)) == 0)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+}
+
+/* Convert a node set to boolean */
+axis2_bool_t
+axiom_xpath_convert_to_boolean(
+ axutil_array_list_t *node_set,
+ axiom_xpath_context_t *context)
+{
+ if(axutil_array_list_size(node_set, context->env) == 0)
+ {
+ return AXIS2_FALSE;
+ }
+ else if(axutil_array_list_size(node_set, context->env) >= 2)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ axiom_xpath_result_node_t *node = axutil_array_list_get(node_set, context->env, 0);
+ axiom_xpath_cast_boolean(node, context);
+
+ return *(axis2_bool_t *)node->value;
+ }
+}
+
+/* Operators */
+
+/* Literal */
+int
+axiom_xpath_literal_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ axiom_xpath_result_node_t *node;
+
+ node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t));
+
+ /* Set the context node to NULL */
+ /* This is not required; it gives some problems */
+ /* context->node = NULL;*/
+
+ node->value = op->par1;
+ node->type = AXIOM_XPATH_TYPE_TEXT;
+
+ axutil_stack_push(context->stack, context->env, node);
+
+ return 1;
+}
+
+/* Number */
+int
+axiom_xpath_number_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ axiom_xpath_result_node_t *node;
+
+ node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t));
+
+ /* Set the context node to NULL */
+ /* This is not required; it gives some problems */
+ /* context->node = NULL;*/
+
+ node->value = op->par1;
+ node->type = AXIOM_XPATH_TYPE_NUMBER;
+
+ axutil_stack_push(context->stack, context->env, node);
+
+ return 1;
+}
+
+/* Path Expression */
+int
+axiom_xpath_path_expression_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ int filter_res_n, n_nodes = 0;
+ axiom_xpath_operation_t *rel_loc_op;
+ axiom_xpath_operator_t rel_loc_func;
+ axutil_array_list_t *arr;
+ axiom_xpath_result_node_t *res_node;
+ int i;
+
+ /* Filter operation */
+ if(op->op1 == AXIOM_XPATH_PARSE_END)
+ {
+ return 0;
+ }
+
+ filter_res_n = axiom_xpath_evaluate_operation(context, op->op1);
+
+ /* Relative location path */
+ if(op->op2 == AXIOM_XPATH_PARSE_END)
+ {
+ return filter_res_n;
+ }
+
+ rel_loc_op = AXIOM_XPATH_OPR_GET(op->op2);
+ rel_loc_func = axiom_xpath_get_operator(rel_loc_op);
+
+ /* Array list to add all results from the filter expression */
+ arr = axutil_array_list_create(context->env, 0);
+
+ for(i = 0; i < filter_res_n; i++)
+ {
+ axutil_array_list_add(arr, context->env, axutil_stack_pop(context->stack, context->env));
+ }
+
+ /* Evaluate relative location path for all results from the
+ filter expression */
+ for(i = 0; i < axutil_array_list_size(arr, context->env); i++)
+ {
+ res_node = (axiom_xpath_result_node_t *)axutil_array_list_get(arr, context->env, i);
+
+ if(res_node->type == AXIOM_XPATH_TYPE_NODE)
+ {
+ context->node = (axiom_node_t *)res_node->value;
+ context->position = i + 1;
+ context->size = filter_res_n;
+
+ n_nodes += rel_loc_func(context, rel_loc_op);
+ }
+
+ AXIS2_FREE(context->env->allocator, res_node);
+ }
+
+ axutil_array_list_free(arr, context->env);
+
+ return n_nodes;
+}
+
+/* Or Expression */
+int
+axiom_xpath_orexpr_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ axiom_xpath_result_node_t *node;
+ axiom_xpath_result_node_t *res_node;
+ int n_nodes[2];
+ int i, j;
+ int op12[2];
+ axutil_array_list_t *arr[2];
+
+ op12[0] = op->op1;
+ op12[1] = op->op2;
+
+ /* Evaluate both operands and get number of results */
+ for(i = 0; i < 2; i++)
+ {
+ if(op12[i] == AXIOM_XPATH_PARSE_END)
+ {
+ continue;
+ }
+
+ n_nodes[i] = axiom_xpath_evaluate_operation(context, op12[i]);
+ }
+
+ for(i = 1; i >= 0; i--)
+ {
+ arr[i] = axutil_array_list_create(context->env, 0);
+
+ for(j = 0; j < n_nodes[i]; j++)
+ {
+ axutil_array_list_add(arr[i], context->env, axutil_stack_pop(context->stack,
+ context->env));
+ }
+ }
+
+ node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t));
+
+ node->type = AXIOM_XPATH_TYPE_BOOLEAN;
+ node->value = NULL;
+
+ /* Checking equality
+ - If any node from the first set is equal to any node from the second set
+ the result is true */
+ if(axiom_xpath_convert_to_boolean(arr[0], context) || axiom_xpath_convert_to_boolean(arr[1],
+ context))
+ {
+ AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_TRUE);
+
+ axutil_stack_push(context->stack, context->env, node);
+ }
+ else
+ {
+ AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_FALSE);
+
+ axutil_stack_push(context->stack, context->env, node);
+ }
+
+ for (i = 1; i >= 0; i--)
+ {
+ for (j = 0; j < n_nodes[i]; j++)
+ {
+ res_node = (axiom_xpath_result_node_t *)axutil_array_list_get(arr[i], context->env, j);
+ AXIS2_FREE(context->env->allocator, res_node);
+ }
+
+ axutil_array_list_free(arr[i], context->env);
+ }
+
+ return 1;
+}
+
+/* And Expression */
+int
+axiom_xpath_andexpr_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ axiom_xpath_result_node_t *node;
+ axiom_xpath_result_node_t *res_node;
+ int n_nodes[2];
+ int i, j;
+ int op12[2];
+ axutil_array_list_t *arr[2];
+
+ op12[0] = op->op1;
+ op12[1] = op->op2;
+
+ /* Evaluate both operands and get number of results */
+ for(i = 0; i < 2; i++)
+ {
+ if(op12[i] == AXIOM_XPATH_PARSE_END)
+ {
+ continue;
+ }
+
+ n_nodes[i] = axiom_xpath_evaluate_operation(context, op12[i]);
+ }
+
+ for(i = 1; i >= 0; i--)
+ {
+ arr[i] = axutil_array_list_create(context->env, 0);
+
+ for(j = 0; j < n_nodes[i]; j++)
+ {
+ axutil_array_list_add(arr[i], context->env, axutil_stack_pop(context->stack,
+ context->env));
+ }
+ }
+
+ node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t));
+
+ node->type = AXIOM_XPATH_TYPE_BOOLEAN;
+ node->value = NULL;
+
+ /* Checking equality
+ - If any node from the first set is equal to any node from the second set
+ the result is true */
+ if(axiom_xpath_convert_to_boolean(arr[0], context) && axiom_xpath_convert_to_boolean(arr[1],
+ context))
+ {
+ AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_TRUE);
+
+ axutil_stack_push(context->stack, context->env, node);
+ }
+ else
+ {
+ AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_FALSE);
+
+ axutil_stack_push(context->stack, context->env, node);
+ }
+
+ for (i = 1; i >= 0; i--)
+ {
+ for (j = 0; j < n_nodes[i]; j++)
+ {
+ res_node = (axiom_xpath_result_node_t *)axutil_array_list_get(arr[i], context->env, j);
+ AXIS2_FREE(context->env->allocator, res_node);
+ }
+
+ axutil_array_list_free(arr[i], context->env);
+ }
+
+ return 1;
+}
+
+/* Equal Expression */
+int
+axiom_xpath_equalexpr_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ axiom_xpath_result_node_t *node;
+ axiom_xpath_result_node_t *res_node;
+ int n_nodes[2];
+ int i, j;
+ int op12[2];
+ axutil_array_list_t *arr[2];
+
+ op12[0] = op->op1;
+ op12[1] = op->op2;
+
+ /* Evaluate both operands and get number of results */
+ for(i = 0; i < 2; i++)
+ {
+ if(op12[i] == AXIOM_XPATH_PARSE_END)
+ {
+ continue;
+ }
+
+ n_nodes[i] = axiom_xpath_evaluate_operation(context, op12[i]);
+ }
+
+ for(i = 1; i >= 0; i--)
+ {
+ arr[i] = axutil_array_list_create(context->env, 0);
+
+ for(j = 0; j < n_nodes[i]; j++)
+ {
+ axutil_array_list_add(arr[i], context->env, axutil_stack_pop(context->stack,
+ context->env));
+ }
+ }
+
+ node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t));
+
+ node->type = AXIOM_XPATH_TYPE_BOOLEAN;
+ node->value = NULL;
+
+ /* Checking equality
+ - If any node from the first set is equal to any node from the second set
+ the result is true */
+ for(i = 0; i < n_nodes[0]; i++)
+ {
+ for(j = 0; j < n_nodes[1]; j++)
+ {
+ if(axiom_xpath_compare_equal(axutil_array_list_get(arr[0], context->env, i),
+ axutil_array_list_get(arr[1], context->env, j), context))
+ {
+ AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_TRUE);
+
+ axutil_stack_push(context->stack, context->env, node);
+
+ break;
+ }
+ }
+
+ if(j < n_nodes[1])
+ {
+ break;
+ }
+ }
+
+ if(!node->value)
+ {
+ AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_FALSE);
+
+ axutil_stack_push(context->stack, context->env, node);
+ }
+
+ for (i = 1; i >= 0; i--)
+ {
+ for (j = 0; j < n_nodes[i]; j++)
+ {
+ res_node =(axiom_xpath_result_node_t *)axutil_array_list_get(arr[i], context->env, j);
+ AXIS2_FREE(context->env->allocator, res_node);
+ }
+
+ axutil_array_list_free(arr[i], context->env);
+ }
+
+ return 1;
+}
+
+/* Union */
+int
+axiom_xpath_union_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ int n_nodes = 0;
+ int i;
+ int op12[2];
+
+ op12[0] = op->op1;
+ op12[1] = op->op2;
+
+ for(i = 0; i < 2; i++)
+ {
+ if(op12[i] == AXIOM_XPATH_PARSE_END)
+ {
+ continue;
+ }
+
+ n_nodes += axiom_xpath_evaluate_operation(context, op12[i]);
+ }
+
+ return n_nodes;
+}
+
+/* Set context node depending on whether relative or absolute location path */
+int
+axiom_xpath_start_node_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ int n_nodes = 0;
+
+ if(op->op1 == AXIOM_XPATH_PARSE_END)
+ {
+ return 0;
+ }
+
+ if(op->opr == AXIOM_XPATH_OPERATION_ROOT_NODE)
+ {
+ context->node = context->root_node;
+ n_nodes += axiom_xpath_evaluate_operation(context, op->op1);
+ }
+ else if(op->opr == AXIOM_XPATH_OPERATION_CONTEXT_NODE)
+ {
+ n_nodes += axiom_xpath_evaluate_operation(context, op->op1);
+ }
+
+ return n_nodes;
+}
+
+/* Step */
+int
+axiom_xpath_step_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ axiom_xpath_operation_t * node_test_op;
+ axiom_xpath_iterator_t iter;
+ axiom_xpath_axis_t axis;
+
+ if(op->op1 == AXIOM_XPATH_PARSE_END)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Node test operator empty\n");
+#endif
+
+ return AXIOM_XPATH_EVALUATION_ERROR;
+ }
+
+ if(op->op2 == AXIOM_XPATH_PARSE_END)
+ {
+ return 0;
+ }
+
+ /* Get the name */
+ node_test_op = AXIOM_XPATH_OPR_GET(op->op1);
+
+ /* Get the axis */
+ if(!node_test_op->par2)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf("axis is NULL in the step operator\n");
+#endif
+ return AXIOM_XPATH_EVALUATION_ERROR;
+ }
+ axis = *((axiom_xpath_axis_t *)node_test_op->par2);
+
+ /* Get the iteration for the axis */
+ iter = axiom_xpath_get_iterator(axis);
+
+ return iter(context, op->op1 /* node test */, op->op2 /* next step */, node_test_op->op1 /* predicate */);
+}
+
+/* Predicates */
+axis2_bool_t
+axiom_xpath_evaluate_predicate_condition(
+ axiom_xpath_context_t *context,
+ int n_nodes)
+{
+ axiom_xpath_result_node_t *res;
+ int i;
+
+ if(n_nodes <= 0)
+ {
+ return AXIS2_FALSE;
+ }
+ else if(n_nodes > 1)
+ {
+ for(i = 0; i < n_nodes; i++)
+ {
+ res = (axiom_xpath_result_node_t *)axutil_stack_pop(context->stack, context->env);
+
+ if (res->type > AXIOM_XPATH_TYPE_NAMESPACE)
+ {
+ AXIS2_FREE(context->env->allocator, res->value);
+ }
+
+ AXIS2_FREE(context->env->allocator, res);
+ }
+
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ res = (axiom_xpath_result_node_t *)axutil_stack_pop(context->stack, context->env);
+
+ if(res->type == AXIOM_XPATH_TYPE_NUMBER)
+ {
+ if(*(double *)(res->value) == context->position)
+ {
+ AXIS2_FREE(context->env->allocator, res);
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ AXIS2_FREE(context->env->allocator, res);
+ return AXIS2_FALSE;
+ }
+ }
+ else if(res->type == AXIOM_XPATH_TYPE_BOOLEAN)
+ {
+ if(*(axis2_bool_t *)(res->value))
+ {
+ AXIS2_FREE(context->env->allocator, res);
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ AXIS2_FREE(context->env->allocator, res);
+ return AXIS2_FALSE;
+ }
+ }
+ else
+ {
+ AXIS2_FREE(context->env->allocator, res);
+ return AXIS2_TRUE;
+ }
+ }
+}
+
+/* Predicate */
+int
+axiom_xpath_evaluate_predicate(
+ axiom_xpath_context_t *context,
+ int op_next,
+ int op_predicate)
+{
+ int n_res;
+ axis2_bool_t res;
+
+ axiom_xpath_operation_t * pred_op;
+ axiom_node_t *context_node = context->node;
+
+ if(op_predicate == AXIOM_XPATH_PARSE_END)
+ {
+ return axiom_xpath_evaluate_operation(context, op_next);
+ }
+ else
+ {
+ pred_op = AXIOM_XPATH_OPR_GET(op_predicate);
+
+ pred_op->pos++;
+
+ /* Evaluate the predicate */
+ if(pred_op->op1 != AXIOM_XPATH_PARSE_END)
+ {
+ n_res = axiom_xpath_evaluate_operation(context, pred_op->op1);
+ context->position = pred_op->pos;
+
+ res = axiom_xpath_evaluate_predicate_condition(context, n_res);
+ }
+ else
+ {
+ res = AXIS2_TRUE;
+ }
+ /* A PredicateExpr is evaluated by evaluating the Expr and
+ converting the result to a boolean. If the result is a number,
+ the result will be converted to true if the number is equal to the
+ context position and will be converted to false otherwise; if the
+ result is not a number, then the result will be converted as if
+ by a call to the boolean function. */
+
+ /* Transform the result to number or boolean ? */
+
+ if(res)
+ {
+ context->node = context_node;
+
+ return axiom_xpath_evaluate_predicate(context, op_next, pred_op->op2);
+ }
+ }
+
+ return 0;
+}
+
+/* Node test match */
+axis2_bool_t
+axiom_xpath_node_test_match(
+ axiom_xpath_context_t *context,
+ axiom_xpath_node_test_t *node_test)
+{
+ axiom_types_t type;
+ axiom_element_t *element = NULL;
+ axis2_char_t *name = NULL;
+ axiom_namespace_t *ns = NULL, *xpath_ns = NULL;
+
+ if(!context->node && !context->attribute && !context->ns)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Both context node and attribute are NULL.");
+ printf(" May be a literal or a number.\n");
+#endif
+ return AXIS2_FALSE;
+ }
+ else if(context->node)
+ {
+ /* Test if the node matches */
+ type = axiom_node_get_node_type(context->node, context->env);
+
+ if(type == AXIOM_ELEMENT)
+ {
+ element = axiom_node_get_data_element(context->node, context->env);
+
+ name = axiom_element_get_localname(element, context->env);
+
+ ns = axiom_element_get_namespace(element, context->env, context->node);
+ }
+
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_NONE)
+ {
+ return AXIS2_FALSE;
+ }
+ else
+ {
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL || node_test->type
+ == AXIOM_XPATH_NODE_TEST_STANDARD)
+ {
+ if(type != AXIOM_ELEMENT)
+ {
+ return AXIS2_FALSE;
+ }
+
+ /* Check namespace */
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL)
+ {
+ if(!ns && node_test->prefix)
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ else
+ {
+ if((ns && !node_test->prefix) || (!ns && node_test->prefix))
+ {
+ return AXIS2_FALSE;
+ }
+ }
+
+ if(ns && node_test->prefix)
+ {
+ xpath_ns = axiom_xpath_get_namespace(context, node_test->prefix);
+
+ if(!xpath_ns)
+ {
+ return AXIS2_FALSE;
+ }
+
+ if(axutil_strcmp(axiom_namespace_get_uri(ns, context->env),
+ axiom_namespace_get_uri(xpath_ns, context->env)))
+ {
+ return AXIS2_FALSE;
+ }
+ }
+
+ /* Check local name */
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL)
+ {
+ return AXIS2_TRUE;
+ }
+ else if(node_test->type == AXIOM_XPATH_NODE_TEST_STANDARD)
+ {
+ if(name && axutil_strcmp(node_test->name, name) == 0)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ }
+ else if(node_test->type == AXIOM_XPATH_NODE_TYPE_COMMENT)
+ {
+ if(type == AXIOM_COMMENT)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ else if(node_test->type == AXIOM_XPATH_NODE_TYPE_PI)
+ {
+ if(type == AXIOM_PROCESSING_INSTRUCTION)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ else if(node_test->type == AXIOM_XPATH_NODE_TYPE_NODE)
+ {
+ if(type == AXIOM_ELEMENT)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ else if(node_test->type == AXIOM_XPATH_NODE_TYPE_TEXT)
+ {
+ if(type == AXIOM_TEXT)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ }
+ }
+ /* Attributes */
+ else if(context->attribute)
+ {
+ name = axiom_attribute_get_localname(context->attribute, context->env);
+ ns = axiom_attribute_get_namespace(context->attribute, context->env);
+
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_NONE)
+ {
+ return AXIS2_FALSE;
+ }
+ else
+ {
+ /* Check namespace */
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL)
+ {
+ if(!ns && node_test->prefix)
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ else
+ {
+ if((ns && !node_test->prefix) || (!ns && node_test->prefix))
+ {
+ return AXIS2_FALSE;
+ }
+ }
+
+ if(ns && node_test->prefix)
+ {
+ xpath_ns = axiom_xpath_get_namespace(context, node_test->prefix);
+
+ if(!xpath_ns)
+ {
+ return AXIS2_FALSE;
+ }
+
+ if(axutil_strcmp(axiom_namespace_get_uri(ns, context->env),
+ axiom_namespace_get_uri(xpath_ns, context->env)))
+ {
+ return AXIS2_FALSE;
+ }
+ }
+
+ /* Check local name */
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL)
+ {
+ return AXIS2_TRUE;
+ }
+ else if(node_test->type == AXIOM_XPATH_NODE_TEST_STANDARD)
+ {
+ if(name && axutil_strcmp(node_test->name, name) == 0)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ }
+ }
+
+ /* Namespace */
+ else if(context->ns)
+ {
+ /* Prefix is checked ??? If changed to uri the cast
+ method in xpath.c needs to be changed as well */
+ name = axiom_namespace_get_prefix(context->ns, context->env);
+ ns = NULL;
+
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_NONE)
+ {
+ return AXIS2_FALSE;
+ }
+ else
+ {
+ /* Check namespace */
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL)
+ {
+ if(!ns && node_test->prefix)
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ else
+ {
+ if((ns && !node_test->prefix) || (!ns && node_test->prefix))
+ {
+ return AXIS2_FALSE;
+ }
+ }
+
+ if(ns && node_test->prefix)
+ {
+ xpath_ns = axiom_xpath_get_namespace(context, node_test->prefix);
+
+ if(!xpath_ns)
+ {
+ return AXIS2_FALSE;
+ }
+
+ if(axutil_strcmp(axiom_namespace_get_uri(ns, context->env),
+ axiom_namespace_get_uri(xpath_ns, context->env)))
+ {
+ return AXIS2_FALSE;
+ }
+ }
+
+ /* Check local name */
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL)
+ {
+ return AXIS2_TRUE;
+ }
+ else if(node_test->type == AXIOM_XPATH_NODE_TEST_STANDARD)
+ {
+ if(name && axutil_strcmp(node_test->name, name) == 0)
+ {
+ return AXIS2_TRUE;
+ }
+ else
+ {
+ return AXIS2_FALSE;
+ }
+ }
+ }
+ }
+
+ return AXIS2_FALSE;
+}
+
+int
+axiom_xpath_function_call_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ axiom_xpath_function_t func = axiom_xpath_get_function(context, op->par1);
+ int n_args = 0;
+
+ if(!func)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Function %s not found\n", (char *)op->par1);
+#endif
+
+ return AXIOM_XPATH_EVALUATION_ERROR;
+ }
+
+ if(op->op1 != AXIOM_XPATH_PARSE_END)
+ {
+ n_args = axiom_xpath_evaluate_operation(context, op->op1);
+ }
+
+ return func(context, n_args);
+}
+
+int
+axiom_xpath_argument_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ int n_args = 0;
+
+ if(op->op1 != AXIOM_XPATH_PARSE_END)
+ {
+ n_args += axiom_xpath_evaluate_operation(context, op->op1);
+ }
+
+ if(op->op2 != AXIOM_XPATH_PARSE_END)
+ {
+ n_args += axiom_xpath_evaluate_operation(context, op->op1);
+ }
+
+ return n_args;
+}
+
+/* Collect the current node to the results list */
+int
+axiom_xpath_collect_operator(
+ axiom_xpath_context_t *context,
+ axiom_xpath_operation_t * op)
+{
+ axiom_xpath_result_node_t *node;
+
+ node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t));
+
+ if(context->node)
+ {
+ node->value = context->node;
+ node->type = AXIOM_XPATH_TYPE_NODE;
+ }
+ else if(context->attribute)
+ {
+ node->value = context->attribute;
+ node->type = AXIOM_XPATH_TYPE_ATTRIBUTE;
+ }
+ else if(context->ns)
+ {
+ node->value = context->ns;
+ node->type = AXIOM_XPATH_TYPE_NAMESPACE;
+ }
+
+ axutil_stack_push(context->stack, context->env, node);
+
+ return 1;
+}
+
+/* Returns a pointer to the respective processing function */
+axiom_xpath_operator_t
+axiom_xpath_get_operator(
+ axiom_xpath_operation_t * op)
+{
+ switch(op->opr)
+ {
+ case AXIOM_XPATH_OPERATION_STEP:
+ return axiom_xpath_step_operator;
+
+ case AXIOM_XPATH_OPERATION_ROOT_NODE:
+ case AXIOM_XPATH_OPERATION_CONTEXT_NODE:
+ return axiom_xpath_start_node_operator;
+
+ case AXIOM_XPATH_OPERATION_RESULT:
+ return axiom_xpath_collect_operator;
+
+ case AXIOM_XPATH_OPERATION_UNION:
+ return axiom_xpath_union_operator;
+
+ case AXIOM_XPATH_OPERATION_OR_EXPR:
+ return axiom_xpath_orexpr_operator;
+
+ case AXIOM_XPATH_OPERATION_AND_EXPR:
+ return axiom_xpath_andexpr_operator;
+
+ case AXIOM_XPATH_OPERATION_EQUAL_EXPR:
+ return axiom_xpath_equalexpr_operator;
+
+ case AXIOM_XPATH_OPERATION_LITERAL:
+ return axiom_xpath_literal_operator;
+
+ case AXIOM_XPATH_OPERATION_NUMBER:
+ return axiom_xpath_number_operator;
+
+ case AXIOM_XPATH_OPERATION_PATH_EXPRESSION:
+ return axiom_xpath_path_expression_operator;
+
+ case AXIOM_XPATH_OPERATION_FUNCTION_CALL:
+ return axiom_xpath_function_call_operator;
+
+ case AXIOM_XPATH_OPERATION_ARGUMENT:
+ return axiom_xpath_argument_operator;
+
+ default:
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Unidentified operation.\n");
+#endif
+
+ return NULL;
+ }
+}
+
+/* Returns a pointer to the respective processing function */
+axiom_xpath_iterator_t
+axiom_xpath_get_iterator(
+ axiom_xpath_axis_t axis)
+{
+ switch(axis)
+ {
+ case AXIOM_XPATH_AXIS_CHILD:
+ return axiom_xpath_child_iterator;
+
+ case AXIOM_XPATH_AXIS_DESCENDANT:
+ return axiom_xpath_descendant_iterator;
+
+ case AXIOM_XPATH_AXIS_PARENT:
+ return axiom_xpath_parent_iterator;
+
+ case AXIOM_XPATH_AXIS_ANCESTOR:
+ return axiom_xpath_ancestor_iterator;
+
+ case AXIOM_XPATH_AXIS_FOLLOWING_SIBLING:
+ return axiom_xpath_following_sibling_iterator;
+
+ case AXIOM_XPATH_AXIS_PRECEDING_SIBLING:
+ return axiom_xpath_preceding_sibling_iterator;
+
+ case AXIOM_XPATH_AXIS_FOLLOWING:
+ return axiom_xpath_following_iterator;
+
+ case AXIOM_XPATH_AXIS_PRECEDING:
+ return axiom_xpath_preceding_iterator;
+
+ case AXIOM_XPATH_AXIS_ATTRIBUTE:
+ return axiom_xpath_attribute_iterator;
+
+ case AXIOM_XPATH_AXIS_NAMESPACE:
+ return axiom_xpath_namespace_iterator;
+
+ case AXIOM_XPATH_AXIS_SELF:
+ return axiom_xpath_self_iterator;
+
+ case AXIOM_XPATH_AXIS_DESCENDANT_OR_SELF:
+ return axiom_xpath_descendant_self_iterator;
+
+ case AXIOM_XPATH_AXIS_ANCESTOR_OR_SELF:
+ return axiom_xpath_ancestor_self_iterator;
+
+ default:
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Unidentified axis.\n");
+#endif
+
+ return NULL;
+ }
+}
+
+int
+axiom_xpath_evaluate_operation(
+ axiom_xpath_context_t *context,
+ int op)
+{
+ axiom_xpath_operation_t * operation;
+ axiom_xpath_operator_t function;
+
+ /* Get a pointer to the operation */
+ operation = AXIOM_XPATH_OPR_GET(op);
+
+ /* Get the funciton which processes the operations */
+ function = axiom_xpath_get_operator(operation);
+
+ return function(context, operation);
+}
diff --git a/axiom/src/xpath/xpath_internals_engine.h b/axiom/src/xpath/xpath_internals_engine.h
new file mode 100755
index 0000000..bffc8a7
--- /dev/null
+++ b/axiom/src/xpath/xpath_internals_engine.h
@@ -0,0 +1,265 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AXIOM_XPATH_INTERNALS_ENGINE_H
+#define AXIOM_XPATH_INTERNALS_ENGINE_H
+
+#include "xpath_internals.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /**
+ * @defgroup axiom_xpath_engine engine
+ * @ingroup axiom_xpath
+ * @{
+ */
+
+
+ /* Macros */
+
+ /** Set node->value to _value */
+#define AXIOM_XPATH_CAST_SET_VALUE(_type, _value) { \
+ _type * _var; \
+ if(node->value \
+ && node->type != AXIOM_XPATH_TYPE_NODE \
+ && node->type != AXIOM_XPATH_TYPE_ATTRIBUTE \
+ && node->type != AXIOM_XPATH_TYPE_NAMESPACE) \
+ { AXIS2_FREE(context->env->allocator, node->value); } \
+ _var = AXIS2_MALLOC(context->env->allocator, sizeof(_type)); \
+ *_var = _value; \
+ node->value = (void *) _var; \
+}
+
+ /* Functions */
+
+ /**
+ * Evaluate an XPath context, which containes a parsed expression
+ *
+ * @param context XPath context
+ * @return Result set
+ */
+ axiom_xpath_result_t* axiom_xpath_run(axiom_xpath_context_t *context);
+
+ /**
+ * Finds the operator function for a given operation
+ *
+ * @param op Operation
+ * @return Pointer to the function which process the given operation
+ */
+ axiom_xpath_operator_t axiom_xpath_get_operator(axiom_xpath_operation_t * op);
+
+ /**
+ * Get the iterotor for give axis
+ *
+ * @param axis XPath axis
+ * @return Pointer to the function which iterater through the given axis
+ */
+ axiom_xpath_iterator_t axiom_xpath_get_iterator(axiom_xpath_axis_t axis);
+
+ /* Operators */
+
+ /**
+ * Select the start node depending on whether it is an absolute or relative location path
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_start_node_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+ /**
+ * Add the context node or attribute to the results stack
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_collect_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+ /**
+ * Process union operator
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_union_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+ /**
+ * Perform or operation
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack; which is one
+ */
+ int axiom_xpath_orexpr_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+ /**
+ * Perform and operation
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack; which is one
+ */
+ int axiom_xpath_andexpr_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+ /**
+ * Perform equality test operation
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack; which is one
+ */
+ int axiom_xpath_equalexpr_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+ /**
+ * Evaluate function call operation
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack; which is one
+ */
+ int axiom_xpath_function_call_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+ /**
+ * Evaluate argument operation
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack; which is one
+ */
+ int axiom_xpath_argument_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+ /**
+ * Process a path expression
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_path_expression_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+ /**
+ * Process a number; push the value to the stack
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack; which is one
+ */
+ int axiom_xpath_number_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+ /**
+ * Process a literal; push the string to the stack
+ *
+ * @param context XPath context
+ * @param op XPath operation
+ * @return Number of nodes added to the stack; which is one
+ */
+ int axiom_xpath_literal_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op);
+
+
+ /**
+ * Converts an XPath result to a boolean result
+ *
+ * @param node Result
+ * @param context XPath context
+ */
+ void axiom_xpath_cast_boolean(axiom_xpath_result_node_t *node, axiom_xpath_context_t *context);
+
+ /**
+ * Converts an XPath result to a number
+ *
+ * @param node Result
+ * @param context XPath context
+ */
+ void axiom_xpath_cast_number(axiom_xpath_result_node_t *node, axiom_xpath_context_t *context);
+
+ /**
+ * Converts an XPath result to a string
+ *
+ * @param node Result
+ * @param context XPath context
+ */
+ void axiom_xpath_cast_string(axiom_xpath_result_node_t *node, axiom_xpath_context_t *context);
+
+ /* Convert a node set to boolean */
+ /**
+ * Convert a XPath node set to boolean
+ *
+ * @param node_set Node set
+ * @return AXIS2_TRUE if true; AXIS2_FALSE otherwise
+ */
+ axis2_bool_t axiom_xpath_convert_to_boolean(axutil_array_list_t *node_set, axiom_xpath_context_t *context);
+
+ /**
+ * Test if two result nodes are equal
+ *
+ * @param node1 First node
+ * @param node2 Second node
+ * @param context XPath context
+ * @return AXIS2_TRUE if equal; AXIS2_FALSE otherwise
+ */
+ axis2_bool_t axiom_xpath_compare_equal(axiom_xpath_result_node_t *node1, axiom_xpath_result_node_t *node2, axiom_xpath_context_t *context);
+
+ /**
+ * Test if the axiom node matches node test
+ *
+ * @param context XPath context
+ * @param node_test Node test
+ * @return AXIS2_TRUE if matches; AXIS2_FALSE otherwise
+ */
+ axis2_bool_t axiom_xpath_node_test_match(axiom_xpath_context_t *context, axiom_xpath_node_test_t *node_test);
+
+ /**
+ * Evaluate if the predicate is true
+ *
+ * @param context XPath context
+ * @param n_nodes Number of results after evaluating the expression in the predicate
+ * @return AXIS2_TRUE if matches; AXIS2_FALSE otherwise
+ */
+ axis2_bool_t axiom_xpath_evaluate_predicate_condition(axiom_xpath_context_t *context, int n_nodes);
+
+ /**
+ * Evaluate if the predicate(s) is true using axiom_xpath_evaluate_predicate_condition and executes the operation op_next
+ *
+ * @param context XPath context
+ * @param op_next The operation to be executed if all predicates are true
+ * @param op_predicate Reference to predicate
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_evaluate_predicate(axiom_xpath_context_t *context, int op_next, int op_predicate);
+
+ /**
+ * Evaluate operation pointed by op
+ *
+ * @param context XPath context
+ * @param op The index of the operation in the operations list
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_evaluate_operation(axiom_xpath_context_t *context, int op);
+
+ /** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/axiom/src/xpath/xpath_internals_iterators.c b/axiom/src/xpath/xpath_internals_iterators.c
new file mode 100644
index 0000000..225bea6
--- /dev/null
+++ b/axiom/src/xpath/xpath_internals_iterators.c
@@ -0,0 +1,588 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <axiom_xpath.h>
+#include "xpath_internals.h"
+#include "xpath_internals_engine.h"
+#include "xpath_internals_iterators.h"
+
+
+/* child */
+int
+axiom_xpath_child_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes_tot = 0;
+ int n_nodes;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *cur = NULL;
+ axiom_node_t *context_node = NULL;
+ /* For streaming */
+ axiom_node_t *prev = NULL;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+ cur = axiom_node_get_first_child(context->node, context->env);
+
+ while(cur != NULL)
+ {
+ n_nodes = 0;
+ context->node = cur;
+ prev = cur;
+ cur = axiom_node_get_next_sibling(cur, context->env);
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes = axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ n_nodes_tot += n_nodes;
+ }
+ }
+
+ /* Change the context node back to what it was */
+ context->node = context_node;
+
+ return n_nodes_tot;
+}
+
+/* descendant */
+int
+axiom_xpath_descendant_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *child = NULL;
+ axiom_node_t *context_node = NULL;
+ axutil_stack_t *stack;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+
+ /* Setting up the stack */
+ stack = axutil_stack_create(context->env);
+
+ child = axiom_node_get_first_child(context->node, context->env);
+ while(child)
+ {
+ axutil_stack_push(stack, context->env, child);
+ child = axiom_node_get_first_child(child, context->env);
+ }
+
+ /* Processing nodes */
+ while(axutil_stack_size(stack, context->env) > 0)
+ {
+ child = (axiom_node_t *)axutil_stack_pop(stack, context->env);
+
+ context->node = child;
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ child = axiom_node_get_next_sibling(child, context->env);
+ while(child)
+ {
+ axutil_stack_push(stack, context->env, child);
+ child = axiom_node_get_first_child(child, context->env);
+ }
+ }
+
+ context->node = context_node;
+
+ axutil_stack_free(stack, context->env);
+
+ return n_nodes;
+}
+
+/* parent */
+int
+axiom_xpath_parent_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *parent = NULL;
+ axiom_node_t *context_node = NULL;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+
+ parent = axiom_node_get_parent(context->node, context->env);
+
+ if(parent != NULL)
+ {
+ context->node = parent;
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes = axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+ }
+
+ /* Change the context node back to what it was */
+ context->node = context_node;
+
+ return n_nodes;
+}
+
+/* ancestor axis */
+int
+axiom_xpath_ancestor_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *cur = NULL;
+ axiom_node_t *context_node = NULL;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+ cur = axiom_node_get_parent(context->node, context->env);
+
+ while(cur != NULL)
+ {
+ context->node = cur;
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ cur = axiom_node_get_parent(cur, context->env);
+ }
+
+ /* Change the context node back to what it was */
+ context->node = context_node;
+
+ return n_nodes;
+}
+
+/* following-sibling axis */
+int
+axiom_xpath_following_sibling_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *cur = NULL;
+ axiom_node_t *context_node = NULL;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+ cur = axiom_node_get_next_sibling(context->node, context->env);
+
+ while(cur != NULL)
+ {
+ context->node = cur;
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ cur = axiom_node_get_next_sibling(cur, context->env);
+ }
+
+ /* Change the context node back to what it was */
+ context->node = context_node;
+
+ return n_nodes;
+}
+
+/* preceding-sibling axis */
+int
+axiom_xpath_preceding_sibling_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *cur = NULL;
+ axiom_node_t *context_node = NULL;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+ cur = axiom_node_get_previous_sibling(context->node, context->env);
+
+ while(cur != NULL)
+ {
+ context->node = cur;
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ cur = axiom_node_get_previous_sibling(cur, context->env);
+ }
+
+ /* Change the context node back to what it was */
+ context->node = context_node;
+
+ return n_nodes;
+}
+
+/* following */
+int
+axiom_xpath_following_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *child = NULL, *parent = NULL;
+ axiom_node_t *context_node = NULL;
+ axutil_stack_t *stack;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+
+ /* Setting up the stack */
+ stack = axutil_stack_create(context->env);
+ axutil_stack_push(stack, context->env, context->node);
+
+ parent = context->node;
+
+ while(parent)
+ {
+ axutil_stack_push(stack, context->env, parent);
+
+ while(axutil_stack_size(stack, context->env) > 0)
+ {
+ child = (axiom_node_t *)axutil_stack_pop(stack, context->env);
+
+ child = axiom_node_get_next_sibling(child, context->env);
+
+ while(child)
+ {
+ context->node = child;
+ if(axiom_xpath_node_test_match(context,
+ (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ axutil_stack_push(stack, context->env, child);
+ child = axiom_node_get_first_child(child, context->env);
+ }
+ }
+ parent = axiom_node_get_parent(parent, context->env);
+ }
+
+ /* Change the context node back to what it was */
+ context->node = context_node;
+
+ axutil_stack_free(stack, context->env);
+
+ return n_nodes;
+}
+
+/* preceding */
+int
+axiom_xpath_preceding_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *child = NULL, *parent = NULL;
+ axiom_node_t *context_node = NULL;
+ axutil_stack_t *stack;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+
+ /* Setting up the stack */
+ stack = axutil_stack_create(context->env);
+
+ parent = context->node;
+
+ while(parent)
+ {
+ axutil_stack_push(stack, context->env, parent);
+
+ while(axutil_stack_size(stack, context->env) > 0)
+ {
+ child = (axiom_node_t *)axutil_stack_pop(stack, context->env);
+
+ child = axiom_node_get_previous_sibling(child, context->env);
+
+ while(child)
+ {
+ context->node = child;
+ if(axiom_xpath_node_test_match(context,
+ (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ axutil_stack_push(stack, context->env, child);
+
+ child = axiom_node_get_last_child(child, context->env);
+ }
+ }
+ parent = axiom_node_get_parent(parent, context->env);
+ }
+
+ /* Change the context node back to what it was */
+ context->node = context_node;
+
+ axutil_stack_free(stack, context->env);
+
+ return n_nodes;
+}
+
+/* attribute axis */
+int
+axiom_xpath_attribute_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_types_t type;
+ axiom_node_t *context_node = NULL;
+ axiom_element_t *element;
+ axutil_hash_t *ht;
+ axutil_hash_index_t *hi;
+
+ /* void *key;
+ * axis2_ssize_t klen;
+ */
+ void *attr;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+
+ type = axiom_node_get_node_type(context_node, context->env);
+
+ if(type != AXIOM_ELEMENT)
+ {
+ return 0;
+ }
+
+ element = axiom_node_get_data_element(context_node, context->env);
+
+ context->node = NULL;
+
+ ht = axiom_element_get_all_attributes(element, context->env);
+
+ if(ht)
+ {
+ for(hi = axutil_hash_first(ht, context->env); hi; hi = axutil_hash_next(context->env, hi))
+ {
+ attr = &context->attribute;
+ axutil_hash_this(hi, NULL, NULL, attr);
+
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+ }
+ }
+
+ context->node = context_node;
+ context->attribute = NULL;
+
+ return n_nodes;
+}
+
+/* namespace axis */
+int
+axiom_xpath_namespace_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_types_t type;
+ axiom_node_t *context_node = NULL;
+ axiom_element_t *element;
+ axutil_hash_t *ht;
+ axutil_hash_index_t *hi;
+
+ /* void *key;
+ * axis2_ssize_t klen;
+ */
+
+ void *ns;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+
+ type = axiom_node_get_node_type(context_node, context->env);
+
+ if(type != AXIOM_ELEMENT)
+ {
+ return 0;
+ }
+
+ element = axiom_node_get_data_element(context_node, context->env);
+
+ context->node = NULL;
+
+ ht = axiom_element_get_namespaces(element, context->env);
+
+ if(ht)
+ {
+ for(hi = axutil_hash_first(ht, context->env); hi; hi = axutil_hash_next(context->env, hi))
+ {
+ ns = &context->ns;
+ axutil_hash_this(hi, NULL, NULL, ns);
+
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+ }
+ }
+
+ context->node = context_node;
+ context->ns = NULL;
+
+ return n_nodes;
+}
+
+/* self axis */
+int
+axiom_xpath_self_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *context_node = NULL;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ context->node = context_node;
+
+ return n_nodes;
+}
+
+/* descendant-or-self axis */
+int
+axiom_xpath_descendant_self_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *child = NULL;
+ axiom_node_t *context_node = NULL;
+ axutil_stack_t *stack;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ /* Setting up the stack */
+ stack = axutil_stack_create(context->env);
+
+ child = axiom_node_get_first_child(context->node, context->env);
+ while(child)
+ {
+ axutil_stack_push(stack, context->env, child);
+ child = axiom_node_get_first_child(child, context->env);
+ }
+
+ /* Processing nodes */
+ while(axutil_stack_size(stack, context->env) > 0)
+ {
+ child = (axiom_node_t *)axutil_stack_pop(stack, context->env);
+
+ context->node = child;
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ child = axiom_node_get_next_sibling(child, context->env);
+ while(child)
+ {
+ axutil_stack_push(stack, context->env, child);
+ child = axiom_node_get_first_child(child, context->env);
+ }
+ }
+
+ /* Change the context node back to what it was */
+ context->node = context_node;
+
+ axutil_stack_free(stack, context->env);
+
+ return n_nodes;
+}
+
+/* ancestor-or-self axis */
+int
+axiom_xpath_ancestor_self_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate)
+{
+ int n_nodes = 0;
+ axiom_xpath_operation_t * node_test_op;
+ axiom_node_t *parent = NULL;
+ axiom_node_t *context_node = NULL;
+
+ AXIOM_XPATH_ITERATOR_INITIALIZE;
+
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ parent = axiom_node_get_parent(context->node, context->env);
+
+ while(parent != NULL)
+ {
+ context->node = parent;
+ if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1))
+ {
+ n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate);
+ }
+
+ parent = axiom_node_get_parent(parent, context->env);
+ }
+
+ /* Change the context node back to what it was */
+ context->node = context_node;
+
+ return n_nodes;
+}
diff --git a/axiom/src/xpath/xpath_internals_iterators.h b/axiom/src/xpath/xpath_internals_iterators.h
new file mode 100755
index 0000000..67d06c4
--- /dev/null
+++ b/axiom/src/xpath/xpath_internals_iterators.h
@@ -0,0 +1,298 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AXIOM_XPATH_INTERNALS_ITERATORS_H
+#define AXIOM_XPATH_INTERNALS_ITERATORS_H
+
+#include <axiom_xpath.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /**
+ * @defgroup axiom_xpath_iterators iterators
+ * @ingroup axiom_xpath
+ * @{
+ */
+
+
+#ifdef AXIOM_XPATH_DEBUG
+#define AXIOM_XPATH_ITERATOR_INITIALIZE { \
+ if(!context->node) { \
+ printf("Context node NULL; cannot evaluate self or descendent axis.\n"); \
+ return AXIOM_XPATH_EVALUATION_ERROR; } \
+ node_test_op = AXIOM_XPATH_OPR_GET(op_node_test); \
+ if(!node_test_op) { \
+ printf("Node test not present.\n"); \
+ return AXIOM_XPATH_EVALUATION_ERROR; } \
+ context_node = context->node; \
+}
+#else
+#define AXIOM_XPATH_ITERATOR_INITIALIZE { \
+ if(!context->node) { \
+ return AXIOM_XPATH_EVALUATION_ERROR; } \
+ node_test_op = AXIOM_XPATH_OPR_GET(op_node_test); \
+ if(!node_test_op) { \
+ return AXIOM_XPATH_EVALUATION_ERROR; } \
+ context_node = context->node; \
+}
+#endif
+
+ /**
+ * Iterate through children
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_child_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through descendents
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_descendant_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through parent node. (Only one node)
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_parent_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through ancestors
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_ancestor_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through siblings following the context node
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_following_sibling_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through sibling preceding the context node
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_preceding_sibling_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through all nodes following the context node
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_following_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through all nodes preceding the context node
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_preceding_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through attributes
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_attribute_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through namespaces defined in the context node
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_namespace_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through self node (Only one node)
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_self_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through descendents and context node
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_descendant_self_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /**
+ * Iterate through ancestors and context node
+ *
+ * @param context XPath context
+ * @param op_node_test Reference to the node test operation
+ * in the parsed expression
+ * @param op_next Reference to the next step in the location path,
+ * in the parsed expression
+ * @param op_predicate Reference to the first predicate in the
+ * parsed expression
+ * @return Number of nodes added to the stack
+ */
+ int axiom_xpath_ancestor_self_iterator(
+ axiom_xpath_context_t *context,
+ int op_node_test,
+ int op_next,
+ int op_predicate);
+
+ /** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/axiom/src/xpath/xpath_internals_parser.c b/axiom/src/xpath/xpath_internals_parser.c
new file mode 100755
index 0000000..a1ce79a
--- /dev/null
+++ b/axiom/src/xpath/xpath_internals_parser.c
@@ -0,0 +1,1245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <axiom_xpath.h>
+#include "xpath_internals.h"
+#include "xpath_internals_parser.h"
+#include <ctype.h>
+
+/* Compile an XPath expression */
+int
+axiom_xpath_compile(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ if(!expr || !expr->expr_str)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Expression in NULL.\n");
+#endif
+
+ return AXIS2_FAILURE;
+ }
+
+ expr->expr_len = (int)axutil_strlen(expr->expr_str);
+
+ expr->operations = axutil_array_list_create(env, 0);
+
+ expr->expr_ptr = 0;
+
+ expr->start = axiom_xpath_compile_orexpr(env, expr);
+
+ if(expr->start == AXIOM_XPATH_PARSE_ERROR)
+ {
+ axutil_array_list_free(expr->operations, env);
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+ else
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Expression successfully parsed\n");
+#endif
+
+ return AXIOM_XPATH_PARSE_SUCCESS;
+ }
+}
+
+/* Parse Or Expression */
+int
+axiom_xpath_compile_orexpr(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op1, op2;
+
+ if(!AXIOM_XPATH_HAS_MORE)
+ {
+ return AXIOM_XPATH_PARSE_END;
+ }
+
+ op1 = axiom_xpath_compile_andexpr(env, expr);
+
+ if(op1 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: AndEpxr expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ while(AXIOM_XPATH_CURRENT == 'o' && AXIOM_XPATH_NEXT(1) == 'r')
+ {
+ AXIOM_XPATH_READ(2);
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ op2 = axiom_xpath_compile_andexpr(env, expr);
+
+ if(op2 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: AndEpxr expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ op1 = AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_OR_EXPR, op1, op2);
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+ }
+
+ return op1;
+}
+
+/* Parse And Expression */
+int
+axiom_xpath_compile_andexpr(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op1, op2;
+
+ if(!AXIOM_XPATH_HAS_MORE)
+ {
+ return AXIOM_XPATH_PARSE_END;
+ }
+
+ op1 = axiom_xpath_compile_equalexpr(env, expr);
+
+ if(op1 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: EqualityExpr expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ while(AXIOM_XPATH_CURRENT == 'a' && AXIOM_XPATH_NEXT(1) == 'n' && AXIOM_XPATH_NEXT(1) == 'd')
+ {
+ AXIOM_XPATH_READ(2);
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ op2 = axiom_xpath_compile_equalexpr(env, expr);
+
+ if(op2 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: EqualityExpr expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ op1 = AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_AND_EXPR, op1, op2);
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+ }
+
+ return op1;
+}
+
+/* Parse Equality Expression */
+int
+axiom_xpath_compile_equalexpr(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op1, op2;
+
+ if(!AXIOM_XPATH_HAS_MORE)
+ {
+ return AXIOM_XPATH_PARSE_END;
+ }
+
+ op1 = axiom_xpath_compile_union(env, expr);
+
+ if(op1 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: UnionExpr expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ while(AXIOM_XPATH_CURRENT == '=')
+ {
+ AXIOM_XPATH_SKIP_WHITESPACES;
+ AXIOM_XPATH_READ(1);
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ op2 = axiom_xpath_compile_union(env, expr);
+
+ if(op2 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: UnionExpr expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ op1 = AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_EQUAL_EXPR, op1, op2);
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+ }
+
+ return op1;
+}
+
+/* Parse Union */
+int
+axiom_xpath_compile_union(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op1, op2;
+
+ if(!AXIOM_XPATH_HAS_MORE)
+ {
+ return AXIOM_XPATH_PARSE_END;
+ }
+
+ op1 = axiom_xpath_compile_path_expression(env, expr);
+
+ if(op1 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: PathExpr expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ if(AXIOM_XPATH_CURRENT == '|')
+ {
+ AXIOM_XPATH_READ(1);
+ AXIOM_XPATH_SKIP_WHITESPACES;
+ op2 = axiom_xpath_compile_union(env, expr);
+
+ if(op2 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: UnionExpr expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ return AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_UNION, op1, op2);
+ }
+
+ /* Just a location path */
+ return op1;
+}
+
+/* Compile Filter expression */
+int
+axiom_xpath_compile_filter(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op = AXIOM_XPATH_PARSE_END;
+
+ if(AXIOM_XPATH_CURRENT == '(')
+ {
+ AXIOM_XPATH_READ(1);
+ op = axiom_xpath_compile_orexpr(env, expr);
+ AXIOM_XPATH_SKIP_WHITESPACES;
+ if(AXIOM_XPATH_CURRENT == ')')
+ {
+ AXIOM_XPATH_READ(1);
+ return op;
+ }
+ else
+ {
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+ }
+ else if(AXIOM_XPATH_CURRENT == '\'' || AXIOM_XPATH_CURRENT == '\"')
+ {
+ return AXIOM_XPATH_PUSH_PAR(AXIOM_XPATH_OPERATION_LITERAL, axiom_xpath_compile_literal(env,
+ expr), NULL, AXIOM_XPATH_PARSE_END);
+ }
+ else if(isdigit(AXIOM_XPATH_CURRENT) || (AXIOM_XPATH_CURRENT == '.' && isdigit(
+ AXIOM_XPATH_NEXT(1))))
+ {
+ return AXIOM_XPATH_PUSH_PAR(AXIOM_XPATH_OPERATION_NUMBER, axiom_xpath_compile_number(env,
+ expr), NULL, AXIOM_XPATH_PARSE_END);
+ }
+ else if(AXIOM_XPATH_CURRENT == '$')
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: Variables are not supported, yet - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+ }
+ else
+ {
+ return axiom_xpath_compile_function_call(env, expr);
+ }
+
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: Invalid Filter expression - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ /* TODO: functions and variables */
+}
+
+/* Parse Path expression (not a location path) */
+int
+axiom_xpath_path_compile_path_expression_filter(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op_filter, op_next;
+
+ op_filter = axiom_xpath_compile_filter(env, expr);
+
+ if(op_filter == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: FilterExpr expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ if(AXIOM_XPATH_NEXT(0) == '/' && AXIOM_XPATH_NEXT(1) == '/')
+ {
+ AXIOM_XPATH_READ(2);
+
+ op_next = axiom_xpath_compile_relative_location(env, expr);
+
+ if(op_next == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: RelativeLocation expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ op_next = AXIOM_XPATH_WRAP_SELF_DESCENDANT(op_next);
+ }
+ else if(AXIOM_XPATH_NEXT(0) == '/')
+ {
+ AXIOM_XPATH_READ(1);
+
+ op_next = axiom_xpath_compile_relative_location(env, expr);
+
+ if(op_next == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: RelativeLocation expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+ }
+ else
+ {
+ op_next = AXIOM_XPATH_PARSE_END;
+ }
+
+ return AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_PATH_EXPRESSION, op_filter, op_next);
+}
+
+/* Parse Path expression */
+int
+axiom_xpath_compile_path_expression(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int temp_ptr = expr->expr_ptr;
+ axis2_char_t *name;
+ axis2_char_t *node_types[] = { "comment", "node", "processing-instruction", "text" };
+ axis2_char_t filter_start[] = { '$', '\'', '\"', '(' };
+ int i;
+
+ /* if | FilterExpr
+ | FilterExpr '/' RelativeLocationPath
+ | FilterExpr '//' RelativeLocationPath */
+ for(i = 0; i < 4; i++)
+ {
+ if(AXIOM_XPATH_CURRENT == filter_start[i])
+ {
+ return axiom_xpath_path_compile_path_expression_filter(env, expr);
+ }
+ }
+
+ if(isdigit(AXIOM_XPATH_CURRENT) || (AXIOM_XPATH_CURRENT == '.' && isdigit(AXIOM_XPATH_NEXT(1))))
+ {
+ return axiom_xpath_path_compile_path_expression_filter(env, expr);
+ }
+
+ /* Funciton calls */
+ name = axiom_xpath_compile_ncname(env, expr);
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ if(name != NULL && AXIOM_XPATH_CURRENT == '(')
+ {
+ expr->expr_ptr = temp_ptr;
+ for(i = 0; i < 4; i++)
+ {
+ /* If node type */
+ if(axutil_strcmp(name, node_types[i]) == 0)
+ {
+ return axiom_xpath_compile_location_path(env, expr);
+ }
+ }
+
+ return axiom_xpath_path_compile_path_expression_filter(env, expr);
+ }
+
+ expr->expr_ptr = temp_ptr;
+
+ return axiom_xpath_compile_location_path(env, expr);
+}
+
+/* Parses Location Path */
+int
+axiom_xpath_compile_location_path(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op1;
+ axiom_xpath_operation_type_t opr;
+
+ if(!AXIOM_XPATH_HAS_MORE)
+ {
+ return AXIOM_XPATH_PARSE_END;
+ }
+
+ if(AXIOM_XPATH_CURRENT == '/')
+ {
+ /* Descendent */
+ if(AXIOM_XPATH_NEXT(1) == '/')
+ {
+ opr = AXIOM_XPATH_OPERATION_CONTEXT_NODE;
+ AXIOM_XPATH_READ(2);
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ op1 = axiom_xpath_compile_relative_location(env, expr);
+
+ if(op1 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: RelativeLocation expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ op1 = AXIOM_XPATH_WRAP_SELF_DESCENDANT(op1);
+ }
+ else
+ {
+ opr = AXIOM_XPATH_OPERATION_ROOT_NODE;
+ AXIOM_XPATH_READ(1);
+
+ op1 = axiom_xpath_compile_relative_location(env, expr);
+
+ if(op1 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: RelativeLocation expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+ }
+ }
+ else
+ {
+ opr = AXIOM_XPATH_OPERATION_CONTEXT_NODE;
+
+ op1 = axiom_xpath_compile_relative_location(env, expr);
+
+ if(op1 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: RelativeLocation expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+ }
+
+ if(op1 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: RelativeLocation expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ return AXIOM_XPATH_PUSH(opr, op1, AXIOM_XPATH_PARSE_END);
+}
+
+/* Parses Relative Location Path */
+int
+axiom_xpath_compile_relative_location(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op_step, op_next;
+
+ if(!AXIOM_XPATH_HAS_MORE)
+ {
+ return AXIOM_XPATH_PARSE_END;
+ }
+
+ op_step = axiom_xpath_compile_step(env, expr);
+ op_next = AXIOM_XPATH_PARSE_END; /* Will change if there are more steps */
+
+ if(op_step == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: Step expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ if(AXIOM_XPATH_NEXT(0) == '/' && AXIOM_XPATH_NEXT(1) == '/')
+ {
+ AXIOM_XPATH_READ(2);
+
+ op_next = axiom_xpath_compile_relative_location(env, expr);
+
+ if(op_next == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: RelativeLocation expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ op_next = AXIOM_XPATH_WRAP_SELF_DESCENDANT(op_next);
+ }
+ else if(AXIOM_XPATH_NEXT(0) == '/')
+ {
+ AXIOM_XPATH_READ(1);
+
+ op_next = axiom_xpath_compile_relative_location(env, expr);
+
+ if(op_next == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: RelativeLocation expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+ }
+
+ /* End of the location path */
+ if(op_next == AXIOM_XPATH_PARSE_END)
+ {
+ op_next = AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_RESULT, AXIOM_XPATH_PARSE_END,
+ AXIOM_XPATH_PARSE_END);
+ }
+
+ return AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_STEP, op_step, op_next);
+}
+
+/* Parses Step */
+int
+axiom_xpath_compile_step(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op_predicate = AXIOM_XPATH_PARSE_END;
+ axiom_xpath_node_test_t *node_test;
+ int temp_ptr;
+ axis2_char_t *name = NULL;
+ axiom_xpath_axis_t axis = AXIOM_XPATH_AXIS_NONE;
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ /* . and .. */
+ if(AXIOM_XPATH_CURRENT == '.')
+ {
+ if(AXIOM_XPATH_NEXT(1) == '.')
+ {
+ AXIOM_XPATH_READ(2);
+ axis = AXIOM_XPATH_AXIS_PARENT;
+ }
+ else
+ {
+ AXIOM_XPATH_READ(1);
+ axis = AXIOM_XPATH_AXIS_SELF;
+ }
+
+ return AXIOM_XPATH_PUSH_PAR(AXIOM_XPATH_OPERATION_NODE_TEST,
+ axiom_xpath_create_node_test_node(env), axiom_xpath_create_axis(env, axis),
+ op_predicate);
+ }
+ else if(AXIOM_XPATH_CURRENT == '@')
+ {
+ axis = AXIOM_XPATH_AXIS_ATTRIBUTE;
+
+ AXIOM_XPATH_READ(1);
+ AXIOM_XPATH_SKIP_WHITESPACES;
+ }
+ else
+ {
+ temp_ptr = expr->expr_ptr;
+
+ name = axiom_xpath_compile_ncname(env, expr);
+
+ if(name)
+ {
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ /* An axis */
+ if(AXIOM_XPATH_CURRENT == ':' && AXIOM_XPATH_NEXT(1) == ':')
+ {
+ axis = axiom_xpath_get_axis(env, name);
+
+ if(axis == AXIOM_XPATH_AXIS_NONE)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Parse error: Invalid axis - %s\n", name);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ AXIOM_XPATH_READ(2);
+ AXIOM_XPATH_SKIP_WHITESPACES;
+ }
+ else
+ {
+ axis = AXIOM_XPATH_AXIS_CHILD;
+
+ expr->expr_ptr = temp_ptr;
+ }
+ }
+ else
+ {
+ axis = AXIOM_XPATH_AXIS_CHILD;
+
+ expr->expr_ptr = temp_ptr;
+ }
+ }
+
+ node_test = axiom_xpath_compile_node_test(env, expr);
+
+ if(!node_test)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: NodeTest expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ op_predicate = axiom_xpath_compile_predicate(env, expr);
+
+ if(op_predicate == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: Predicate expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ return AXIOM_XPATH_PUSH_PAR(AXIOM_XPATH_OPERATION_NODE_TEST, node_test,
+ axiom_xpath_create_axis(env, axis), op_predicate);
+}
+
+axiom_xpath_node_test_t*
+axiom_xpath_compile_node_test(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ axis2_char_t* name;
+ axiom_xpath_node_test_t *node_test;
+
+ node_test = AXIS2_MALLOC(env->allocator, sizeof(axiom_xpath_node_test_t));
+ node_test->type = AXIOM_XPATH_NODE_TEST_NONE;
+ node_test->prefix = NULL;
+ node_test->name = NULL;
+ node_test->lit = NULL;
+
+ if(AXIOM_XPATH_CURRENT == '*')
+ {
+ AXIOM_XPATH_READ(1);
+
+ node_test->type = AXIOM_XPATH_NODE_TEST_ALL;
+
+ return node_test;
+ }
+
+ name = axiom_xpath_compile_ncname(env, expr);
+
+ if(!name)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: NCName expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ AXIS2_FREE(env->allocator, node_test);
+
+ return NULL;
+ }
+
+ /* Node type */
+
+ if(AXIOM_XPATH_CURRENT == '(')
+ {
+ AXIOM_XPATH_READ(1);
+
+ if(axutil_strcmp(name, "comment") == 0)
+ {
+ node_test->type = AXIOM_XPATH_NODE_TYPE_COMMENT;
+ }
+ if(axutil_strcmp(name, "node") == 0)
+ {
+ node_test->type = AXIOM_XPATH_NODE_TYPE_NODE;
+ }
+ if(axutil_strcmp(name, "processing-instruction") == 0)
+ {
+ node_test->type = AXIOM_XPATH_NODE_TYPE_PI;
+
+ node_test->lit = axiom_xpath_compile_literal(env, expr);
+ }
+ if(axutil_strcmp(name, "text") == 0)
+ {
+ node_test->type = AXIOM_XPATH_NODE_TYPE_TEXT;
+ }
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ if(node_test->type == AXIOM_XPATH_NODE_TEST_NONE || AXIOM_XPATH_CURRENT != ')')
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Parse error: Invalid node type - %s\n", name);
+#endif
+
+ AXIS2_FREE(env->allocator, node_test);
+
+ return NULL;
+ }
+
+ AXIOM_XPATH_READ(1);
+ }
+ else
+ {
+ node_test->type = AXIOM_XPATH_NODE_TEST_STANDARD;
+
+ if(AXIOM_XPATH_CURRENT == ':')
+ {
+ AXIOM_XPATH_READ(1);
+
+ node_test->prefix = name;
+
+ if(AXIOM_XPATH_CURRENT == '*')
+ {
+ AXIOM_XPATH_READ(1);
+
+ node_test->type = AXIOM_XPATH_NODE_TEST_ALL;
+
+ return node_test;
+ }
+
+ node_test->name = axiom_xpath_compile_ncname(env, expr);
+
+ if(!node_test->name)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: NCName expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ AXIS2_FREE(env->allocator, node_test);
+
+ return NULL;
+ }
+ }
+ else
+ {
+ node_test->name = name;
+ }
+ }
+
+ return node_test;
+}
+
+int
+axiom_xpath_compile_function_call(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ axis2_char_t *name;
+ int op1 = AXIOM_XPATH_PARSE_END;
+
+ name = axiom_xpath_compile_ncname(env, expr);
+
+ if(!name)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: NCName expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ if(AXIOM_XPATH_CURRENT != '(')
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: '(' expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ AXIOM_XPATH_READ(1);
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ if(AXIOM_XPATH_CURRENT != ')')
+ {
+ op1 = axiom_xpath_compile_argument(env, expr);
+ }
+
+ if(AXIOM_XPATH_CURRENT != ')')
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: ')' expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ AXIOM_XPATH_READ(1);
+
+ return AXIOM_XPATH_PUSH_PAR(AXIOM_XPATH_OPERATION_FUNCTION_CALL, name, NULL, op1);
+}
+
+int
+axiom_xpath_compile_argument(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op1 = AXIOM_XPATH_PARSE_END;
+ int op2 = AXIOM_XPATH_PARSE_END;
+
+ op1 = axiom_xpath_compile_orexpr(env, expr);
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ if(AXIOM_XPATH_CURRENT == ',')
+ {
+ op2 = axiom_xpath_compile_argument(env, expr);
+ }
+
+ return AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_ARGUMENT, op1, op2);
+}
+
+axiom_xpath_node_test_t*
+axiom_xpath_create_node_test_all(
+ const axutil_env_t *env)
+{
+ axiom_xpath_node_test_t *node_test;
+
+ node_test = AXIS2_MALLOC(env->allocator, sizeof(axiom_xpath_node_test_t));
+ node_test->type = AXIOM_XPATH_NODE_TEST_ALL;
+ node_test->prefix = NULL;
+ node_test->name = NULL;
+ node_test->lit = NULL;
+
+ return node_test;
+}
+
+axiom_xpath_node_test_t*
+axiom_xpath_create_node_test_node(
+ const axutil_env_t *env)
+{
+ axiom_xpath_node_test_t *node_test;
+
+ node_test = AXIS2_MALLOC(env->allocator, sizeof(axiom_xpath_node_test_t));
+ node_test->type = AXIOM_XPATH_NODE_TYPE_NODE;
+ node_test->prefix = NULL;
+ node_test->name = NULL;
+ node_test->lit = NULL;
+
+ return node_test;
+}
+
+double*
+axiom_xpath_compile_number(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ double *ret = AXIS2_MALLOC(env->allocator, sizeof(double));
+ double res = 0, dec = 0.1;
+ axis2_bool_t dot = AXIS2_FALSE;
+
+ *ret = 0;
+
+ while(1)
+ {
+ if(isdigit(AXIOM_XPATH_CURRENT))
+ {
+ if(!dot)
+ {
+ res = res * 10 + (AXIOM_XPATH_CURRENT - '0');
+ }
+ else
+ {
+ res += dec * (AXIOM_XPATH_CURRENT - '0');
+ dec /= 10;
+ }
+ }
+ else if(AXIOM_XPATH_CURRENT == '.')
+ {
+ if(dot)
+ {
+ return ret;
+ }
+ else
+ {
+ dot = AXIS2_TRUE;
+ dec = 0.1;
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ AXIOM_XPATH_READ(1);
+ }
+
+ *ret = res;
+ return ret;
+}
+
+axis2_char_t*
+axiom_xpath_compile_literal(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ axis2_char_t lit[255];
+ int i = 0;
+ axis2_char_t del;
+
+ if(AXIOM_XPATH_CURRENT == '\"')
+ {
+ del = '\"';
+ }
+ else if(AXIOM_XPATH_CURRENT == '\'')
+ {
+ del = '\'';
+ }
+ else
+ return NULL;
+
+ AXIOM_XPATH_READ(1);
+
+ while(AXIOM_XPATH_HAS_MORE && AXIOM_XPATH_CURRENT != del)
+ {
+ lit[i] = AXIOM_XPATH_CURRENT;
+ AXIOM_XPATH_READ(1);
+ ++i;
+ }
+
+ if(AXIOM_XPATH_HAS_MORE)
+ {
+ AXIOM_XPATH_READ(1);
+ }
+
+ lit[i] = '\0';
+
+ return axutil_strdup(env, lit);
+
+}
+
+/* Get axis for name */
+axiom_xpath_axis_t
+axiom_xpath_get_axis(
+ const axutil_env_t *env,
+ axis2_char_t* name)
+{
+ if(axutil_strcmp(name, "child") == 0)
+ {
+ return AXIOM_XPATH_AXIS_CHILD;
+ }
+ else if(axutil_strcmp(name, "descendant") == 0)
+ {
+ return AXIOM_XPATH_AXIS_DESCENDANT;
+ }
+ else if(axutil_strcmp(name, "parent") == 0)
+ {
+ return AXIOM_XPATH_AXIS_PARENT;
+ }
+ else if(axutil_strcmp(name, "ancestor") == 0)
+ {
+ return AXIOM_XPATH_AXIS_ANCESTOR;
+ }
+ else if(axutil_strcmp(name, "following-sibling") == 0)
+ {
+ return AXIOM_XPATH_AXIS_FOLLOWING_SIBLING;
+ }
+ else if(axutil_strcmp(name, "preceding-sibling") == 0)
+ {
+ return AXIOM_XPATH_AXIS_PRECEDING_SIBLING;
+ }
+ else if(axutil_strcmp(name, "following") == 0)
+ {
+ return AXIOM_XPATH_AXIS_FOLLOWING;
+ }
+ else if(axutil_strcmp(name, "preceding") == 0)
+ {
+ return AXIOM_XPATH_AXIS_PRECEDING;
+ }
+ else if(axutil_strcmp(name, "attribute") == 0)
+ {
+ return AXIOM_XPATH_AXIS_ATTRIBUTE;
+ }
+ else if(axutil_strcmp(name, "namespace") == 0)
+ {
+ return AXIOM_XPATH_AXIS_NAMESPACE;
+ }
+ else if(axutil_strcmp(name, "self") == 0)
+ {
+ return AXIOM_XPATH_AXIS_SELF;
+ }
+ else if(axutil_strcmp(name, "descendant-or-self") == 0)
+ {
+ return AXIOM_XPATH_AXIS_DESCENDANT_OR_SELF;
+ }
+ else if(axutil_strcmp(name, "ancestor-or-self") == 0)
+ {
+ return AXIOM_XPATH_AXIS_ANCESTOR_OR_SELF;
+ }
+ else
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Unidentified axis name.\n");
+#endif
+
+ return AXIOM_XPATH_AXIS_NONE;
+ }
+}
+
+/* Parse Predicate */
+int
+axiom_xpath_compile_predicate(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ int op1, op_next_predicate;
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ if(!AXIOM_XPATH_HAS_MORE || AXIOM_XPATH_CURRENT != '[')
+ {
+ return AXIOM_XPATH_PARSE_END;
+ }
+
+ AXIOM_XPATH_READ(1);
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ /* A PredicateExpr is evaluated by evaluating the Expr and converting the result to a boolean.
+ If the result is a number, the result will be converted to true if the number is equal to the
+ context position and will be converted to false otherwise; if the result is not a number,
+ then the result will be converted as if by a call to the boolean function. */
+
+ op1 = axiom_xpath_compile_orexpr(env, expr);
+
+ if(op1 == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: EqualExpr expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ AXIOM_XPATH_SKIP_WHITESPACES;
+
+ if(AXIOM_XPATH_CURRENT != ']')
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: ] expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ AXIOM_XPATH_READ(1);
+
+ op_next_predicate = axiom_xpath_compile_predicate(env, expr);
+
+ if(op_next_predicate == AXIOM_XPATH_PARSE_ERROR)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf(
+ "Parse error: Predicate expected - %s\n",
+ expr->expr_str + expr->expr_ptr);
+#endif
+
+ return AXIOM_XPATH_PARSE_ERROR;
+ }
+
+ return AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_PREDICATE, op1, op_next_predicate);
+}
+
+/* Parse Node Test */
+axis2_char_t *
+axiom_xpath_compile_ncname(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr)
+{
+ axis2_char_t name[255];
+ int i = 0;
+
+ if(!isalpha(AXIOM_XPATH_CURRENT) && AXIOM_XPATH_CURRENT != '_')
+ {
+ return NULL;
+ }
+
+ /* TODO: Add CombiningChar and Extender
+ * Link http://www.w3.org/TR/REC-xml/#NT-NameChar */
+ while(AXIOM_XPATH_HAS_MORE && (isalnum(AXIOM_XPATH_CURRENT) || AXIOM_XPATH_CURRENT == '_'
+ || AXIOM_XPATH_CURRENT == '.' || AXIOM_XPATH_CURRENT == '-'))
+ {
+ name[i] = AXIOM_XPATH_CURRENT;
+ AXIOM_XPATH_READ(1);
+ ++i;
+ }
+
+ name[i] = '\0';
+
+ return axutil_strdup(env, name);
+}
+
+/* Supporting functions */
+int
+axiom_xpath_add_operation(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr,
+ axiom_xpath_operation_type_t op_type,
+ int op1,
+ int op2,
+ void *par1,
+ void *par2)
+{
+ axiom_xpath_operation_t *op;
+
+ op = AXIS2_MALLOC(env->allocator, sizeof(axiom_xpath_operation_t));
+ op->opr = op_type;
+ op->op1 = op1;
+ op->op2 = op2;
+
+ op->pos = 0;
+
+ op->par1 = par1;
+ op->par2 = par2;
+
+ axutil_array_list_add(expr->operations, env, op);
+
+ return axutil_array_list_size(expr->operations, env) - 1;
+}
+
+axiom_xpath_axis_t *
+axiom_xpath_create_axis(
+ const axutil_env_t *env,
+ axiom_xpath_axis_t axis)
+{
+ axiom_xpath_axis_t *axis_p = AXIS2_MALLOC(env->allocator, sizeof(axiom_xpath_axis_t));
+
+ *axis_p = axis;
+ return axis_p;
+}
diff --git a/axiom/src/xpath/xpath_internals_parser.h b/axiom/src/xpath/xpath_internals_parser.h
new file mode 100755
index 0000000..7d1a2d0
--- /dev/null
+++ b/axiom/src/xpath/xpath_internals_parser.h
@@ -0,0 +1,421 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AXIOM_XPATH_INTERNALS_PARSER_H
+#define AXIOM_XPATH_INTERNALS_PARSER_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /**
+ * @defgroup axiom_xpath_parser parser
+ * @ingroup axiom_xpath
+ * @{
+ */
+
+
+ /* Macros */
+
+ /** Get the current character in the expression */
+#define AXIOM_XPATH_CURRENT (expr->expr_ptr < expr->expr_len ? \
+ expr->expr_str[expr->expr_ptr] : -1)
+
+ /** Get a character after the current */
+#define AXIOM_XPATH_NEXT(ind) (expr->expr_ptr + ind < expr->expr_len ? \
+ expr->expr_str[expr->expr_ptr + ind] : -1)
+
+ /** Increment the pointer to the expression */
+#define AXIOM_XPATH_READ(n) (expr->expr_ptr += n)
+
+ /** Check if expression has finished parsing */
+#define AXIOM_XPATH_HAS_MORE (expr->expr_ptr < expr->expr_len)
+
+ /** Skip white spaces */
+#define AXIOM_XPATH_SKIP_WHITESPACES \
+ { while(AXIOM_XPATH_CURRENT == ' ') \
+ AXIOM_XPATH_READ(1); \
+ }
+
+ /** Wrape an operation in a self_or_descendent step; used to handle '//' */
+#define AXIOM_XPATH_WRAP_SELF_DESCENDANT(_op2) \
+ axiom_xpath_add_operation(env, expr, AXIOM_XPATH_OPERATION_STEP, \
+ axiom_xpath_add_operation(env, expr, AXIOM_XPATH_OPERATION_NODE_TEST, \
+ AXIOM_XPATH_PARSE_END, AXIOM_XPATH_PARSE_END, \
+ axiom_xpath_create_node_test_node(env), \
+ axiom_xpath_create_axis(env, AXIOM_XPATH_AXIS_DESCENDANT_OR_SELF)), \
+ _op2, NULL, NULL)
+
+ /** Adds an operation */
+#define AXIOM_XPATH_PUSH(_opr, _op1, _op2) axiom_xpath_add_operation( \
+ env, expr, _opr, _op1, _op2, NULL, NULL)
+
+ /** Adds an operation with parameters */
+#define AXIOM_XPATH_PUSH_PAR(_opr, _par1, _par2, _op1) axiom_xpath_add_operation( \
+ env, expr, _opr, _op1, AXIOM_XPATH_PARSE_END, (void *)_par1, (void *)_par2)
+
+ /* Functions */
+
+ /**
+ * Add an operation to the operations array
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @param op_type Type of the operation
+ * @param op1 First operand
+ * @param op2 Second operand
+ * @param par1 First parameter
+ * @param par2 Second parameter
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_add_operation(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr,
+ axiom_xpath_operation_type_t op_type,
+ int op1,
+ int op2,
+ void *par1,
+ void *par2);
+
+ /**
+ * Compile a XPath expression
+ *
+ * [14] Expr ::= OrExpr
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the main operation in the array
+ */
+ int axiom_xpath_compile(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile an equals expression
+ *
+ * ***Not completed***
+ * [23] EqualityExpr ::= UnionExpr '=' UnionExpr
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_equalexpr(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile an union
+ *
+ * [18] UnionExpr ::= PathExpr
+ * | UnionExpr '|' PathExpr
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_union(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile a path expression
+ *
+ * [19] PathExpr ::= LocationPath
+ * | FilterExpr
+ * | FilterExpr '/' RelativeLocationPath
+ * | FilterExpr '//' RelativeLocationPath
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_path_expression(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile a path expression with a filter
+ *
+ * [19] PathExpr ::= FilterExpr
+ * | FilterExpr '/' RelativeLocationPath
+ * | FilterExpr '//' RelativeLocationPath
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_path_compile_path_expression_filter(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile a filter expression
+ *
+ * 20] FilterExpr ::= PrimaryExpr
+ * | FilterExpr Predicate
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_filter(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile a location path
+ *
+ * [1] LocationPath ::= RelativeLocationPath
+ * | AbsoluteLocationPath
+ * [2] AbsoluteLocationPath ::= '/' RelativeLocationPath?
+ * | AbbreviatedAbsoluteLocationPath
+ *
+ * [10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath
+ * [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_location_path(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile a relative location
+ *
+ * [3] RelativeLocationPath ::= Step
+ * | RelativeLocationPath '/' Step
+ * | AbbreviatedRelativeLocationPath
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_relative_location(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile a step
+ *
+ * [4] Step ::= AxisSpecifier NodeTest Predicate*
+ * | AbbreviatedStep
+ * [5] AxisSpecifier ::= AxisName '::'
+ * | AbbreviatedAxisSpecifier
+ *
+ * [12] AbbreviatedStep ::= '.' | '..'
+ * [13] AbbreviatedAxisSpecifier ::= '@'?
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_step(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compiles an OrExpr.
+ *
+ * [21] OrExpr ::= AndExpr
+ * | OrExpr 'or' AndExpr
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_orexpr(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compiles an AndExpr.
+ *
+ * [22] AndExpr ::= EqualityExpr
+ * | AndExpr 'and' EqualityExpr
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_andexpr(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+
+ /**
+ * Compiles a FunctionCall
+ *
+ * [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')'
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_function_call(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compiles an Argument.
+ *
+ * [17] Argument ::= Expr
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_argument(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile a node test
+ *
+ * [7] NodeTest ::= NameTest
+ * | NodeType '(' ')'
+ * | 'processing-instruction' '(' Literal ')'
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ axiom_xpath_node_test_t* axiom_xpath_compile_node_test(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile a predicate(s)
+ *
+ * [8] Predicate ::= '[' PredicateExpr ']'
+ * [9] PredicateExpr ::= Expr
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return Index of the operation in the array
+ */
+ int axiom_xpath_compile_predicate(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+
+
+ /**
+ * Compile a literal
+ *
+ * [29] Literal ::= '"' [^"]* '"'
+ * | "'" [^']* "'"
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return The literal parsed
+ */
+ axis2_char_t* axiom_xpath_compile_literal(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile a number
+ *
+ * [30] Number ::= Digits ('.' Digits?)?
+ * | '.' Digits
+ * [31] Digits ::= [0-9]+
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return The number parsed
+ */
+ double* axiom_xpath_compile_number(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+ /**
+ * Compile a ncname
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @return The ncname parsed
+ */
+ axis2_char_t* axiom_xpath_compile_ncname(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr);
+
+
+
+ /**
+ * Get the XPath axis by axis name
+ *
+ * [6] AxisName ::= 'ancestor'
+ * | 'ancestor-or-self'
+ * | 'attribute'
+ * | 'child'
+ * | 'descendant'
+ * | 'descendant-or-self'
+ * | 'following'
+ * | 'following-sibling'
+ * | 'namespace'
+ * | 'parent'
+ * | 'preceding'
+ * | 'preceding-sibling'
+ * | 'self'
+ *
+ * @param env Environment must not be null
+ * @param name Name of the axis
+ * @return XPath axis; returns AXIOM_XPATH_AXIS_NONE if invalid name
+ */
+ axiom_xpath_axis_t axiom_xpath_get_axis(
+ const axutil_env_t *env,
+ axis2_char_t* name);
+
+ /**
+ * Create a node test which matches all nodes (*)
+ *
+ * @param env Environment must not be null
+ * @return Node test
+ */
+ axiom_xpath_node_test_t* axiom_xpath_create_node_test_all(
+ const axutil_env_t *env);
+
+ /**
+ * Create a node test which matches all nodes (nodes())
+ *
+ * @param env Environment must not be null
+ * @return Node test
+ */
+ axiom_xpath_node_test_t* axiom_xpath_create_node_test_node(
+ const axutil_env_t *env);
+
+ /**
+ * Create a pointer to an axis; allocate memory using the allocator
+ *
+ * @param env Environment must not be null
+ * @param axis XPath axis
+ * @return Pointer to the axis created
+ */
+ axiom_xpath_axis_t *axiom_xpath_create_axis(
+ const axutil_env_t *env,
+ axiom_xpath_axis_t axis);
+
+ /** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/axiom/src/xpath/xpath_streaming.c b/axiom/src/xpath/xpath_streaming.c
new file mode 100755
index 0000000..0488d5f
--- /dev/null
+++ b/axiom/src/xpath/xpath_streaming.c
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <axiom_xpath.h>
+#include "xpath_streaming.h"
+#include "xpath_internals.h"
+#include "xpath_internals_engine.h"
+
+axiom_xpath_streaming_t
+axiom_xpath_streaming_check_operation(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr,
+ int op_p)
+{
+ axiom_xpath_operation_t *op;
+
+ if(op_p == AXIOM_XPATH_PARSE_END)
+ {
+ return AXIOM_XPATH_STREAMING_CONSTANT;
+ }
+
+ op = AXIOM_XPATH_OPR_EXPR_GET(op_p);
+
+ switch(op->opr)
+ {
+ case AXIOM_XPATH_OPERATION_CONTEXT_NODE:
+ case AXIOM_XPATH_OPERATION_ROOT_NODE:
+ return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1),
+ AXIOM_XPATH_STREAMING_CONSTANT);
+
+ case AXIOM_XPATH_OPERATION_STEP:
+ return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1),
+ AXIOM_XPATH_CHECK(op->op2));
+
+ case AXIOM_XPATH_OPERATION_RESULT:
+ return AXIOM_XPATH_STREAMING_CONSTANT;
+
+ case AXIOM_XPATH_OPERATION_UNION:
+ return axiom_xpath_streaming_combine_independent(AXIOM_XPATH_CHECK(op->op1),
+ AXIOM_XPATH_CHECK(op->op2));
+
+ case AXIOM_XPATH_OPERATION_EQUAL_EXPR:
+ return axiom_xpath_streaming_combine_independent(AXIOM_XPATH_CHECK(op->op1),
+ AXIOM_XPATH_CHECK(op->op2));
+
+ case AXIOM_XPATH_OPERATION_LITERAL:
+ return AXIOM_XPATH_STREAMING_CONSTANT;
+
+ case AXIOM_XPATH_OPERATION_NUMBER:
+ return AXIOM_XPATH_STREAMING_CONSTANT;
+
+ case AXIOM_XPATH_OPERATION_PATH_EXPRESSION:
+ return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1),
+ AXIOM_XPATH_CHECK(op->op2));
+
+ case AXIOM_XPATH_OPERATION_NODE_TEST:
+ return axiom_xpath_streaming_check_node_test(env, expr, op);
+
+ case AXIOM_XPATH_OPERATION_PREDICATE:
+ return axiom_xpath_streaming_check_predicate(env, expr, op_p);
+
+ default:
+#ifdef AXIOM_XPATH_DEBUG
+ printf("Unidentified operation.\n");
+#endif
+
+ return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
+ }
+}
+
+axiom_xpath_streaming_t
+axiom_xpath_streaming_check_predicate(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr,
+ int op_p)
+{
+ axiom_xpath_operation_t *op;
+
+ if(op_p == AXIOM_XPATH_PARSE_END)
+ {
+ return AXIOM_XPATH_STREAMING_CONSTANT;
+ }
+
+ op = AXIOM_XPATH_OPR_EXPR_GET(op_p);
+
+ return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1), AXIOM_XPATH_CHECK(
+ op->op2));
+}
+
+axiom_xpath_streaming_t
+axiom_xpath_streaming_check_node_test(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr,
+ axiom_xpath_operation_t *op)
+{
+ axiom_xpath_axis_t axis = AXIOM_XPATH_AXIS_NONE;
+ axiom_xpath_streaming_t r;
+
+ if(!op->par2)
+ {
+#ifdef AXIOM_XPATH_DEBUG
+ printf("axis is NULL in the step operator\n");
+#endif
+ return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
+ }
+
+ axis = *((axiom_xpath_axis_t *)op->par2);
+
+ switch(axis)
+ {
+ case AXIOM_XPATH_AXIS_ATTRIBUTE:
+ case AXIOM_XPATH_AXIS_CHILD:
+ break;
+
+ default:
+ return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
+ }
+
+ r = axiom_xpath_streaming_check_predicate(env, expr, op->op1);
+
+ if(r != AXIOM_XPATH_STREAMING_ATTRIBUTE && r != AXIOM_XPATH_STREAMING_CONSTANT)
+ {
+ return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
+ }
+
+ if(axis == AXIOM_XPATH_AXIS_ATTRIBUTE)
+ {
+ return AXIOM_XPATH_STREAMING_ATTRIBUTE;
+ }
+ else
+ {
+ return AXIOM_XPATH_STREAMING_SUPPORTED;
+ }
+}
+
+axiom_xpath_streaming_t
+axiom_xpath_streaming_combine_dependent(
+ axiom_xpath_streaming_t r1,
+ axiom_xpath_streaming_t r2)
+{
+ if(r1 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED)
+ {
+ return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
+ }
+ else if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED)
+ {
+ return AXIOM_XPATH_STREAMING_SUPPORTED;
+ }
+ else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE)
+ {
+ return AXIOM_XPATH_STREAMING_ATTRIBUTE;
+ }
+ else
+ {
+ return AXIOM_XPATH_STREAMING_CONSTANT;
+ }
+}
+
+axiom_xpath_streaming_t
+axiom_xpath_streaming_combine_independent(
+ axiom_xpath_streaming_t r1,
+ axiom_xpath_streaming_t r2)
+{
+ if(r1 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED)
+ {
+ return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
+ }
+ else if(r1 == AXIOM_XPATH_STREAMING_CONSTANT || r2 == AXIOM_XPATH_STREAMING_CONSTANT)
+ {
+ if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED)
+ {
+ return AXIOM_XPATH_STREAMING_SUPPORTED;
+ }
+ else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE)
+ {
+ return AXIOM_XPATH_STREAMING_ATTRIBUTE;
+ }
+ else
+ {
+ return AXIOM_XPATH_STREAMING_CONSTANT;
+ }
+ }
+ else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE)
+ {
+ if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED)
+ {
+ return AXIOM_XPATH_STREAMING_SUPPORTED;
+ }
+ else
+ {
+ return AXIOM_XPATH_STREAMING_ATTRIBUTE;
+ }
+ }
+ else
+ {
+ return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
+ }
+}
+
diff --git a/axiom/src/xpath/xpath_streaming.h b/axiom/src/xpath/xpath_streaming.h
new file mode 100755
index 0000000..63b1ee5
--- /dev/null
+++ b/axiom/src/xpath/xpath_streaming.h
@@ -0,0 +1,126 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AXIOM_XPATH_STREAMING_H
+#define AXIOM_XPATH_STREAMING_H
+
+#include "xpath_internals.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /**
+ * @defgroup axiom_xpath_streaming streaming
+ * @ingroup axiom_xpath
+ * @{
+ */
+
+
+ /**
+ * XPath streaming support
+ */
+ typedef enum axiom_xpath_streaming_t
+ {
+ AXIOM_XPATH_STREAMING_NOT_SUPPORTED = 0,
+ AXIOM_XPATH_STREAMING_SUPPORTED,
+ AXIOM_XPATH_STREAMING_CONSTANT,
+ AXIOM_XPATH_STREAMING_ATTRIBUTE
+ } axiom_xpath_streaming_t;
+
+ /** Check whether the given expression is supported on streaming XML */
+#define AXIOM_XPATH_CHECK(op) axiom_xpath_streaming_check_operation(env, expr, op)
+
+ /** Get an operation from the list of operations */
+#define AXIOM_XPATH_OPR_EXPR_GET(ind) (axiom_xpath_operation_t *) \
+ axutil_array_list_get(expr->operations, env, ind)
+
+ /**
+ * Checks whether the given expression is supported on streaming XML
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @param op_p Index of the operation in the list of operations
+ * @return Whether the given operation can be evaluated on streaming XML
+ */
+ axiom_xpath_streaming_t axiom_xpath_streaming_check_operation(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr,
+ int op_p);
+
+ /**
+ * Checks whether the predicate is supported on streaming XML.
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @param op_p Index of the operation in the list of operations
+ * @return Whether the given operation can be evaluated on streaming XML
+ */
+ axiom_xpath_streaming_t axiom_xpath_streaming_check_predicate(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr,
+ int op_p);
+
+ /**
+ * Checks whether the predicate is supported on streaming XML.
+ *
+ * @param env Environment must not be null
+ * @param expr A pointer to the XPath expression
+ * @param op Index of the operation in the list of operations
+ * @return Whether the given operation can be evaluated on streaming XML
+ */
+ axiom_xpath_streaming_t axiom_xpath_streaming_check_node_test(
+ const axutil_env_t *env,
+ axiom_xpath_expression_t* expr,
+ axiom_xpath_operation_t* op);
+
+
+ /**
+ * Checks whether the two operations can be evaluated on streaming XML
+ * sequencially (one after the other), where the result of the first
+ * operation is the context of the next
+ *
+ * @param r1 Type of first operation
+ * @param r2 Type of second operation
+ * @return Whether the given operations can be evaluated on streaming XML
+ */
+ axiom_xpath_streaming_t axiom_xpath_streaming_combine_dependent(
+ axiom_xpath_streaming_t r1,
+ axiom_xpath_streaming_t r2);
+
+
+ /**
+ * Checks whether the two operations can be evaluated on streaming XML
+ * simultaneousy
+ *
+ * @param r1 Type of first operation
+ * @param r2 Type of second operation
+ * @return Whether the given operations can be evaluated on streaming XML
+ */
+ axiom_xpath_streaming_t axiom_xpath_streaming_combine_independent(
+ axiom_xpath_streaming_t r1,
+ axiom_xpath_streaming_t r2);
+
+ /** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif