| /* |
| * 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); |
| } |