/* * 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 #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, (const void *)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 = (axiom_xpath_function_t)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, (const void *)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 = (axiom_namespace_t *)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; } }