summaryrefslogtreecommitdiffstats
path: root/axiom/src/xpath/xpath_internals_engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'axiom/src/xpath/xpath_internals_engine.c')
-rw-r--r--axiom/src/xpath/xpath_internals_engine.c1203
1 files changed, 1203 insertions, 0 deletions
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);
+}