| /* |
| * 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_node_internal.h" |
| #include "axiom_element_internal.h" |
| #include "axiom_stax_builder_internal.h" |
| #include <axiom_text.h> |
| #include <axiom_data_source.h> |
| #include <axiom_comment.h> |
| #include <axiom_processing_instruction.h> |
| #include <axiom_doctype.h> |
| #include <axiom_document.h> |
| #include <axiom_stax_builder.h> |
| |
| struct axiom_node |
| { |
| /* stax builder */ |
| axiom_stax_builder_t *builder; |
| |
| /* whether current node is the owner of stax builder. If so, it has to free it */ |
| axis2_bool_t own_builder; |
| |
| /** parent node */ |
| axiom_node_t *parent; |
| |
| /** previous sibling */ |
| axiom_node_t *prev_sibling; |
| |
| /** next sibling */ |
| axiom_node_t *next_sibling; |
| |
| /** first child */ |
| axiom_node_t *first_child; |
| |
| /** last child */ |
| axiom_node_t *last_child; |
| |
| /** node type, indicates the type stored in data_element */ |
| axiom_types_t node_type; |
| |
| /** done true means that this node is completely built , false otherwise */ |
| int done; |
| |
| /** instances of an om struct, whose type is defined by node type */ |
| void *data_element; |
| |
| }; |
| |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_create( |
| const axutil_env_t * env) |
| { |
| axiom_node_t *node = NULL; |
| AXIS2_ENV_CHECK(env, NULL); |
| |
| node = (axiom_node_t *)AXIS2_MALLOC(env->allocator, sizeof(axiom_node_t)); |
| if(!node) |
| { |
| env->error->error_number = AXIS2_ERROR_NO_MEMORY; |
| return NULL; |
| } |
| node->first_child = NULL; |
| node->last_child = NULL; |
| node->next_sibling = NULL; |
| node->prev_sibling = NULL; |
| node->parent = NULL; |
| node->node_type = AXIOM_INVALID; |
| node->done = AXIS2_FALSE; |
| node->data_element = NULL; |
| node->builder = NULL; |
| node->own_builder = AXIS2_FALSE; |
| return node; |
| } |
| |
| AXIS2_EXTERN axiom_node_t* AXIS2_CALL |
| axiom_node_create_from_buffer( |
| const axutil_env_t * env, |
| axis2_char_t *buffer) |
| { |
| axiom_xml_reader_t *reader = NULL; |
| axiom_stax_builder_t *builder = NULL; |
| axiom_document_t *document = NULL; |
| axiom_node_t *om_node = NULL; |
| |
| reader = axiom_xml_reader_create_for_memory(env, buffer, axutil_strlen(buffer), "UTF-8", |
| AXIS2_XML_PARSER_TYPE_BUFFER); |
| |
| if(!reader) |
| { |
| return NULL; |
| } |
| |
| builder = axiom_stax_builder_create(env, reader); |
| |
| if(!builder) |
| { |
| return NULL; |
| } |
| document = axiom_stax_builder_get_document(builder, env); |
| if(!document) |
| { |
| AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Document is null for deserialization"); |
| return NULL; |
| } |
| |
| om_node = axiom_document_get_root_element(document, env); |
| |
| if(!om_node) |
| { |
| AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Root element of the document is not found"); |
| return NULL; |
| } |
| axiom_document_build_all(document, env); |
| |
| axiom_stax_builder_free_self(builder, env); |
| |
| return om_node; |
| } |
| |
| static void |
| axiom_node_free_detached_subtree( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| /* Free any child nodes first */ |
| if(om_node->first_child) |
| { |
| axiom_node_t *child_node = om_node->first_child, *next_sibling; |
| while(child_node) |
| { |
| next_sibling = child_node->next_sibling; |
| axiom_node_free_detached_subtree(child_node, env); |
| child_node = next_sibling; |
| } |
| } |
| |
| if(om_node->node_type == AXIOM_ELEMENT) |
| { |
| if(om_node->data_element) |
| { |
| axiom_element_free((axiom_element_t *)(om_node->data_element), env); |
| } |
| } |
| else if(om_node->node_type == AXIOM_COMMENT) |
| { |
| if(om_node->data_element) |
| { |
| axiom_comment_free((axiom_comment_t *)(om_node->data_element), env); |
| } |
| } |
| else if(om_node->node_type == AXIOM_DOCTYPE) |
| { |
| /*axiom_doctype_free((axiom_doctype_t*)(om_node->data_element), env); */ |
| } |
| else if(om_node->node_type == AXIOM_PROCESSING_INSTRUCTION) |
| { |
| if(om_node->data_element) |
| { |
| axiom_processing_instruction_free( |
| (axiom_processing_instruction_t *)(om_node->data_element), env); |
| } |
| } |
| else if(om_node->node_type == AXIOM_TEXT) |
| { |
| if(om_node->data_element) |
| { |
| axiom_text_free((axiom_text_t *)(om_node->data_element), env); |
| } |
| } |
| else if(om_node->node_type == AXIOM_DATA_SOURCE) |
| { |
| if(om_node->data_element) |
| { |
| axiom_data_source_free((axiom_data_source_t *)(om_node->data_element), env); |
| } |
| } |
| |
| /* if the owner of the builder, then free the builder */ |
| if(om_node->own_builder) |
| { |
| axiom_stax_builder_free_internal(om_node->builder, env); |
| } |
| |
| AXIS2_FREE(env->allocator, om_node); |
| } |
| |
| /** |
| * This free function will free an om_element and all the children contained in it |
| * If the node is still attached to the tree, it will be detached first |
| */ |
| AXIS2_EXTERN void AXIS2_CALL |
| axiom_node_free_tree( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| AXIS2_ENV_CHECK(env, void); |
| if(!om_node) |
| { |
| return; |
| } |
| |
| /* Detach this node before freeing it and its subtree. */ |
| axiom_node_detach_without_namespaces(om_node, env); |
| |
| /* Free this node and its subtree */ |
| axiom_node_free_detached_subtree(om_node, env); |
| } |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| axiom_node_add_child( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_node_t * child) |
| { |
| AXIS2_PARAM_CHECK(env->error, child, AXIS2_FAILURE); |
| AXIS2_PARAM_CHECK(env->error, om_node, AXIS2_FAILURE); |
| |
| if(child->parent) |
| { |
| child = axiom_node_detach(child, env); |
| } |
| |
| if(!om_node->first_child) |
| { |
| om_node->first_child = child; |
| } |
| else |
| { |
| axiom_node_t *last_sib = om_node->last_child; |
| last_sib->next_sibling = child; |
| child->prev_sibling = last_sib; |
| } |
| |
| child->parent = om_node; |
| om_node->last_child = child; |
| return AXIS2_SUCCESS; |
| } |
| |
| /** |
| * Detaches given node from the parent and reset the links. will not adjust the namespace as |
| * in the case of axiom_node_detach. |
| * @param om_node node to be detached, cannot be NULL. |
| * @param env Environment. MUST NOT be NULL, . |
| * @return a pointer to detached node,returns NULL on error |
| */ |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_detach_without_namespaces( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| axiom_node_t *parent = NULL; |
| |
| parent = om_node->parent; |
| if(!parent) |
| { |
| /* Node is already detached */ |
| return om_node; |
| } |
| |
| if(!om_node->prev_sibling) |
| { |
| parent->first_child = om_node->next_sibling; |
| } |
| else |
| { |
| axiom_node_t *prev_sib = NULL; |
| prev_sib = om_node->prev_sibling; |
| if(prev_sib) |
| { |
| prev_sib->next_sibling = om_node->next_sibling; |
| } |
| } |
| |
| if(om_node->next_sibling) |
| { |
| axiom_node_t *next_sibling = NULL; |
| next_sibling = om_node->next_sibling; |
| if(next_sibling) |
| { |
| next_sibling->prev_sibling = om_node->prev_sibling; |
| } |
| } |
| |
| if(parent->last_child && (parent->last_child == om_node)) |
| { |
| parent->last_child = om_node->prev_sibling; |
| } |
| |
| /* if the STAX builder's last node is what we are detaching, then we should adjust the |
| * last node if previous sibling is available, set that as the builder's last node. Else set the |
| * parent as the last node*/ |
| if(om_node->builder && (axiom_stax_builder_get_lastnode(om_node->builder, env) == om_node)) |
| { |
| axiom_node_t *lastnode = parent; |
| if(om_node->prev_sibling) |
| { |
| lastnode = om_node->prev_sibling; |
| } |
| axiom_stax_builder_set_lastnode(om_node->builder, env, lastnode); |
| } |
| |
| /* If the node is the owner of the builder, keep a reference to the builder |
| * the builder will be freed when this node is destroyed*/ |
| if(!om_node->own_builder) |
| om_node->builder = NULL; |
| |
| om_node->parent = NULL; |
| om_node->prev_sibling = NULL; |
| om_node->next_sibling = NULL; |
| return om_node; |
| } |
| |
| /** |
| * Detaches given node from the parent and reset the links. Will recreate "namespace defined in |
| * the parent and used in detached node" within detached node itself |
| * @param om_node node to be detached, cannot be NULL. |
| * @param env Environment. MUST NOT be NULL, . |
| * @return a pointer to detached node,returns NULL on error |
| */ |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_detach( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| axutil_hash_t *namespaces = NULL; |
| axiom_element_t *om_element = NULL; |
| |
| if(!om_node) |
| { |
| return NULL; |
| } |
| |
| /* If this is an element node, determine which namespaces are available to it |
| from its parent nodes. */ |
| if((om_node->node_type == AXIOM_ELEMENT) && (om_element = om_node->data_element)) |
| { |
| namespaces = axiom_element_gather_parent_namespaces(om_element, env, om_node); |
| } |
| |
| /* Detach this node from its parent. */ |
| om_node = axiom_node_detach_without_namespaces(om_node, env); |
| |
| /* If this is an element node, ensure that any namespaces available to it or its |
| children remain available after the detach. */ |
| if(om_node && namespaces) |
| { |
| axiom_element_redeclare_parent_namespaces(om_element, env, om_node, namespaces); |
| } |
| |
| if(namespaces) |
| { |
| axutil_hash_free(namespaces, env); |
| } |
| |
| return om_node; |
| } |
| |
| /** |
| Internal function , only used in om and soap |
| not to be used by users |
| */ |
| axis2_status_t AXIS2_CALL |
| axiom_node_set_parent( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_node_t * parent) |
| { |
| |
| if(parent == om_node->parent) |
| { /* same parent already exist */ |
| return AXIS2_SUCCESS; |
| } |
| |
| /* if a new parent is assigned in place of existing one first the node should be detached |
| */ |
| if(om_node->parent) |
| { |
| om_node = axiom_node_detach(om_node, env); |
| } |
| |
| om_node->parent = parent; |
| |
| return AXIS2_SUCCESS; |
| } |
| |
| /** |
| * This will insert a sibling just after the current information item |
| * @param node the node in consideration |
| * @param nodeto_insert the node that will be inserted |
| */ |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| axiom_node_insert_sibling_after( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_node_t * node_to_insert) |
| { |
| axiom_node_t *next_sib = NULL; |
| |
| AXIS2_ENV_CHECK(env, AXIS2_FAILURE); |
| |
| AXIS2_PARAM_CHECK(env->error, node_to_insert, AXIS2_FAILURE); |
| |
| if(!om_node->parent) |
| { |
| /* We shouldn't add a sibling because this node doesn't has a parent. |
| * This can be the root node of the tree*/ |
| return AXIS2_FAILURE; |
| } |
| |
| node_to_insert->parent = om_node->parent; |
| |
| node_to_insert->prev_sibling = om_node; |
| |
| next_sib = om_node->next_sibling; |
| |
| if(next_sib) |
| { |
| next_sib->prev_sibling = node_to_insert; |
| } |
| |
| node_to_insert->next_sibling = om_node->next_sibling; |
| |
| om_node->next_sibling = node_to_insert; |
| return AXIS2_SUCCESS; |
| } |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| axiom_node_insert_sibling_before( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_node_t * node_to_insert) |
| { |
| axiom_node_t *prev_sibling = NULL; |
| |
| AXIS2_ENV_CHECK(env, AXIS2_FAILURE); |
| AXIS2_PARAM_CHECK(env->error, node_to_insert, AXIS2_FAILURE); |
| |
| if(!om_node->parent) |
| { |
| /* We shouldn't add a sibling because this node doesn't has a parent. |
| * This can be the root node of the tree*/ |
| return AXIS2_FAILURE; |
| } |
| |
| node_to_insert->parent = om_node->parent; |
| |
| node_to_insert->prev_sibling = om_node->prev_sibling; |
| |
| node_to_insert->next_sibling = om_node; |
| |
| prev_sibling = om_node->prev_sibling; |
| |
| if(!prev_sibling) |
| { |
| axiom_node_t *parent = om_node->parent; |
| parent->first_child = node_to_insert; |
| } |
| else |
| { |
| axiom_node_t *prev_sibling = om_node->prev_sibling; |
| if(prev_sibling) |
| { |
| prev_sibling->next_sibling = node_to_insert; |
| } |
| } |
| om_node->prev_sibling = node_to_insert; |
| return AXIS2_SUCCESS; |
| } |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| axiom_node_serialize( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_output_t * om_output) |
| { |
| |
| int status = AXIS2_SUCCESS; |
| axiom_node_t *temp_node = NULL; |
| axiom_node_t *nodes[256]; |
| int count = 0; |
| |
| AXIS2_ENV_CHECK(env, AXIS2_FAILURE); |
| |
| if(!om_node) |
| { |
| return AXIS2_SUCCESS; |
| } |
| |
| nodes[count++] = om_node; |
| |
| AXIS2_PARAM_CHECK(env->error, om_output, AXIS2_FAILURE); |
| |
| do |
| { |
| |
| if(om_node->node_type == AXIOM_ELEMENT) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_element_serialize_start_part( |
| (axiom_element_t *)(om_node-> data_element), env, om_output, om_node); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| return status; |
| } |
| } |
| else if(om_node->node_type == AXIOM_DATA_SOURCE) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_data_source_serialize( |
| (axiom_data_source_t *)(om_node->data_element), env, om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| return status; |
| } |
| } |
| else if(om_node->node_type == AXIOM_TEXT) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_text_serialize((axiom_text_t *)(om_node-> data_element), env, |
| om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| return status; |
| } |
| } |
| else if(om_node->node_type == AXIOM_COMMENT) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_comment_serialize((axiom_comment_t *)(om_node-> data_element), env, |
| om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| return status; |
| } |
| } |
| else if(om_node->node_type == AXIOM_DOCTYPE) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_doctype_serialize((axiom_doctype_t *)(om_node-> data_element), env, |
| om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| return status; |
| } |
| } |
| else if(om_node->node_type == AXIOM_PROCESSING_INSTRUCTION) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_processing_instruction_serialize( |
| (axiom_processing_instruction_t *)(om_node->data_element), env, om_output); |
| } |
| |
| if(status != AXIS2_SUCCESS) |
| { |
| return status; |
| } |
| } |
| |
| temp_node = axiom_node_get_first_child(om_node, env); |
| /* serialize children of this node */ |
| if(temp_node) |
| { |
| om_node = temp_node; |
| nodes[count++] = om_node; |
| } |
| else |
| { |
| if(om_node->node_type == AXIOM_ELEMENT) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_element_serialize_end_part( |
| (axiom_element_t *)(om_node-> data_element), env, om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| return status; |
| } |
| } |
| |
| temp_node = axiom_node_get_next_sibling(om_node, env); |
| if(temp_node) |
| { |
| om_node = temp_node; |
| nodes[count - 1] = om_node; |
| } |
| else |
| { |
| while(count > 1 && !temp_node) |
| { |
| count--; |
| om_node = nodes[count - 1]; |
| if(om_node->node_type == AXIOM_ELEMENT) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_element_serialize_end_part( |
| (axiom_element_t *)(om_node->data_element), env, om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| return status; |
| } |
| } |
| |
| temp_node = axiom_node_get_next_sibling(om_node, env); |
| } |
| |
| if(temp_node && count > 1) |
| { |
| om_node = temp_node; |
| nodes[count - 1] = om_node; |
| } |
| else |
| { |
| count--; |
| } |
| } |
| |
| } |
| } |
| while(count > 0); |
| |
| return status; |
| } |
| |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| axiom_node_serialize_sub_tree( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_output_t * om_output) |
| { |
| |
| int status = AXIS2_SUCCESS; |
| axiom_node_t *temp_node = NULL; |
| axiom_node_t *nodes[256]; |
| int count = 0; |
| axutil_hash_t *namespaces = NULL; |
| axutil_hash_t *namespaces_from_parents = NULL; |
| |
| AXIS2_ENV_CHECK(env, AXIS2_FAILURE); |
| |
| if(!om_node) |
| { |
| return AXIS2_SUCCESS; |
| } |
| |
| namespaces = axutil_hash_make(env); |
| if(!namespaces) |
| { |
| AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "hash for namespaces creation failed"); |
| return AXIS2_FAILURE; |
| } |
| |
| namespaces_from_parents = axutil_hash_make(env); |
| if(!namespaces_from_parents) |
| { |
| AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "hash for namespaces_from_parents creation failed"); |
| return AXIS2_FAILURE; |
| } |
| |
| nodes[count++] = om_node; |
| |
| AXIS2_PARAM_CHECK(env->error, om_output, AXIS2_FAILURE); |
| |
| do |
| { |
| |
| if(om_node->node_type == AXIOM_ELEMENT) |
| { |
| if(om_node->data_element) |
| { |
| axutil_hash_t *temp_namespaces = NULL; |
| axutil_hash_t *temp_attributes = NULL; |
| axiom_namespace_t *namespace = NULL; |
| status = axiom_element_serialize_start_part( |
| (axiom_element_t *)(om_node-> data_element), env, om_output, om_node); |
| temp_namespaces = axiom_element_get_namespaces( |
| (axiom_element_t *)(om_node-> data_element), env); |
| if(temp_namespaces) |
| { |
| axutil_hash_t *new_hash = NULL; |
| new_hash = axutil_hash_overlay(temp_namespaces, env, namespaces); |
| if(namespaces) |
| axutil_hash_free(namespaces, env); |
| namespaces = new_hash; |
| } |
| namespace = axiom_element_get_namespace( |
| (axiom_element_t *)(om_node-> data_element), env, om_node); |
| if(namespace) |
| { |
| axiom_namespace_t *ns = NULL; |
| axis2_char_t *prefix = NULL; |
| prefix = axiom_namespace_get_prefix(namespace, env); |
| if(prefix) |
| { |
| ns = axutil_hash_get(namespaces, prefix, AXIS2_HASH_KEY_STRING); |
| if(!ns) |
| { |
| ns = axutil_hash_get(namespaces_from_parents, prefix, |
| AXIS2_HASH_KEY_STRING); |
| if(!ns) |
| { |
| axiom_namespace_serialize(namespace, env, om_output); |
| axutil_hash_set(namespaces_from_parents, prefix, |
| AXIS2_HASH_KEY_STRING, namespace); |
| } |
| } |
| } |
| } |
| |
| temp_attributes = axiom_element_get_all_attributes( |
| (axiom_element_t *)(om_node->data_element), env); |
| if(temp_attributes) |
| { |
| axutil_hash_index_t *hi; |
| void *val; |
| for(hi = axutil_hash_first(temp_attributes, env); hi; hi = axutil_hash_next( |
| env, hi)) |
| { |
| axutil_hash_this(hi, NULL, NULL, &val); |
| |
| if(val) |
| { |
| axiom_namespace_t *ns = NULL; |
| axis2_char_t *prefix = NULL; |
| |
| namespace |
| = axiom_attribute_get_namespace((axiom_attribute_t *)val, env); |
| |
| if(namespace) |
| { |
| prefix = axiom_namespace_get_prefix(namespace, env); |
| if(prefix) |
| { |
| ns = axutil_hash_get(namespaces, prefix, AXIS2_HASH_KEY_STRING); |
| if(!ns) |
| { |
| ns = axutil_hash_get(namespaces_from_parents, prefix, |
| AXIS2_HASH_KEY_STRING); |
| if(!ns) |
| { |
| axiom_namespace_serialize(namespace, env, om_output); |
| axutil_hash_set(namespaces_from_parents, prefix, |
| AXIS2_HASH_KEY_STRING, namespace); |
| } |
| } |
| } |
| } |
| } |
| else |
| { |
| status = AXIS2_FAILURE; |
| } |
| } |
| } |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| break; |
| } |
| } |
| else if(om_node->node_type == AXIOM_DATA_SOURCE) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_data_source_serialize( |
| (axiom_data_source_t *)(om_node->data_element), env, om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| break; |
| } |
| } |
| else if(om_node->node_type == AXIOM_TEXT) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_text_serialize((axiom_text_t *)(om_node-> data_element), env, |
| om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| break; |
| } |
| } |
| else if(om_node->node_type == AXIOM_COMMENT) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_comment_serialize((axiom_comment_t *)(om_node-> data_element), env, |
| om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| break; |
| } |
| } |
| else if(om_node->node_type == AXIOM_DOCTYPE) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_doctype_serialize((axiom_doctype_t *)(om_node-> data_element), env, |
| om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| break; |
| } |
| } |
| else if(om_node->node_type == AXIOM_PROCESSING_INSTRUCTION) |
| { |
| if(om_node->data_element) |
| { |
| status = axiom_processing_instruction_serialize( |
| (axiom_processing_instruction_t *)(om_node->data_element), env, om_output); |
| } |
| |
| if(status != AXIS2_SUCCESS) |
| { |
| break; |
| } |
| } |
| |
| temp_node = axiom_node_get_first_child(om_node, env); |
| /* serialize children of this node */ |
| if(temp_node) |
| { |
| om_node = temp_node; |
| nodes[count++] = om_node; |
| } |
| else |
| { |
| if(om_node->node_type == AXIOM_ELEMENT) |
| { |
| if(om_node->data_element) |
| { |
| |
| axutil_hash_t *temp_attributes = NULL; |
| axiom_namespace_t *namespace = NULL; |
| /* at the writing of end part all the namespaces declared |
| specially to that element should be cancelled */ |
| |
| /* first checking the element namespace */ |
| namespace = axiom_element_get_namespace( |
| (axiom_element_t *)(om_node-> data_element), env, om_node); |
| if(namespace) |
| { |
| axiom_namespace_t *ns = NULL; |
| axis2_char_t *prefix = NULL; |
| prefix = axiom_namespace_get_prefix(namespace, env); |
| if(prefix) |
| { |
| ns = axutil_hash_get(namespaces_from_parents, prefix, |
| AXIS2_HASH_KEY_STRING); |
| if(ns) |
| { |
| axutil_hash_set(namespaces_from_parents, prefix, |
| AXIS2_HASH_KEY_STRING, NULL); |
| } |
| } |
| } |
| |
| /* then checking the attribute namespaces */ |
| |
| temp_attributes = axiom_element_get_all_attributes( |
| (axiom_element_t *)(om_node->data_element), env); |
| if(temp_attributes) |
| { |
| axutil_hash_index_t *hi; |
| void *val; |
| for(hi = axutil_hash_first(temp_attributes, env); hi; hi |
| = axutil_hash_next(env, hi)) |
| { |
| axutil_hash_this(hi, NULL, NULL, &val); |
| |
| if(val) |
| { |
| axiom_namespace_t *ns = NULL; |
| axis2_char_t *prefix = NULL; |
| |
| namespace = axiom_attribute_get_namespace((axiom_attribute_t *)val, |
| env); |
| |
| if(namespace) |
| { |
| prefix = axiom_namespace_get_prefix(namespace, env); |
| if(prefix) |
| { |
| ns = axutil_hash_get(namespaces_from_parents, prefix, |
| AXIS2_HASH_KEY_STRING); |
| if(ns) |
| { |
| axutil_hash_set(namespaces_from_parents, prefix, |
| AXIS2_HASH_KEY_STRING, NULL); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| status = axiom_element_serialize_end_part( |
| (axiom_element_t *)(om_node-> data_element), env, om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| break; |
| } |
| } |
| /* We need to make make sure that om_node is not the root when we take the next sibling */ |
| if(count > 1) |
| { |
| temp_node = axiom_node_get_next_sibling(om_node, env); |
| } |
| if(temp_node) |
| { |
| om_node = temp_node; |
| nodes[count - 1] = om_node; |
| } |
| else |
| { |
| while(count > 1 && !temp_node) |
| { |
| count--; |
| om_node = nodes[count - 1]; |
| if(om_node->node_type == AXIOM_ELEMENT) |
| { |
| if(om_node->data_element) |
| { |
| axutil_hash_t *temp_attributes = NULL; |
| axiom_namespace_t *namespace = NULL; |
| |
| /* similar to the earlier time, whenever the ending is happened |
| * namespaces declared specially to that element should be cancelled */ |
| |
| /* first checking the element namespace */ |
| namespace = axiom_element_get_namespace( |
| (axiom_element_t *)(om_node-> data_element), env, om_node); |
| if(namespace) |
| { |
| axiom_namespace_t *ns = NULL; |
| axis2_char_t *prefix = NULL; |
| prefix = axiom_namespace_get_prefix(namespace, env); |
| if(prefix) |
| { |
| ns = axutil_hash_get(namespaces_from_parents, prefix, |
| AXIS2_HASH_KEY_STRING); |
| if(ns) |
| { |
| axutil_hash_set(namespaces_from_parents, prefix, |
| AXIS2_HASH_KEY_STRING, NULL); |
| } |
| } |
| } |
| |
| /* then checking the attribute namespaces */ |
| |
| temp_attributes = axiom_element_get_all_attributes( |
| (axiom_element_t *)(om_node->data_element), env); |
| if(temp_attributes) |
| { |
| axutil_hash_index_t *hi; |
| void *val; |
| for(hi = axutil_hash_first(temp_attributes, env); hi; hi |
| = axutil_hash_next(env, hi)) |
| { |
| axutil_hash_this(hi, NULL, NULL, &val); |
| |
| if(val) |
| { |
| axiom_namespace_t *ns = NULL; |
| axis2_char_t *prefix = NULL; |
| |
| namespace = axiom_attribute_get_namespace( |
| (axiom_attribute_t *)val, env); |
| |
| if(namespace) |
| { |
| prefix = axiom_namespace_get_prefix(namespace, env); |
| if(prefix) |
| { |
| ns = axutil_hash_get(namespaces_from_parents, |
| prefix, AXIS2_HASH_KEY_STRING); |
| if(ns) |
| { |
| axutil_hash_set(namespaces_from_parents, |
| prefix, AXIS2_HASH_KEY_STRING, NULL); |
| } |
| } |
| } |
| } |
| } |
| } |
| status = axiom_element_serialize_end_part( |
| (axiom_element_t *)(om_node->data_element), env, om_output); |
| } |
| if(status != AXIS2_SUCCESS) |
| { |
| break; |
| } |
| } |
| |
| temp_node = axiom_node_get_next_sibling(om_node, env); |
| } |
| |
| if(temp_node && count > 1) |
| { |
| om_node = temp_node; |
| nodes[count - 1] = om_node; |
| } |
| else |
| { |
| count--; |
| } |
| } |
| } |
| } |
| while(count > 0); |
| |
| axutil_hash_free(namespaces_from_parents, env); |
| axutil_hash_free(namespaces, env); |
| |
| return status; |
| } |
| |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_get_parent( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| return om_node->parent; |
| } |
| |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_get_first_child( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| int token = 0; |
| if(!om_node) |
| { |
| return NULL; |
| } |
| |
| /**********************************************************/ |
| while(!(om_node->first_child) && !(om_node->done) && om_node->builder) |
| { |
| token = axiom_stax_builder_next_with_token(om_node->builder, env); |
| if(token == -1) |
| { |
| return NULL; |
| } |
| } |
| |
| /**********************************************************/ |
| return om_node->first_child; |
| } |
| |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_get_first_element( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| int token = 0; |
| axiom_node_t *first_element; |
| if(!om_node) |
| { |
| return NULL; |
| } |
| |
| /**********************************************************/ |
| while(!(om_node->first_child) && !(om_node->done) && om_node->builder) |
| { |
| token = axiom_stax_builder_next_with_token(om_node->builder, env); |
| if(token == -1) |
| { |
| return NULL; |
| } |
| } |
| |
| /**********************************************************/ |
| first_element = om_node->first_child; |
| |
| while(first_element && (axiom_node_get_node_type(first_element, env) != AXIOM_ELEMENT)) |
| { |
| first_element = axiom_node_get_next_sibling(first_element, env); |
| } |
| |
| return first_element; |
| } |
| |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_get_last_child( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| return om_node->last_child; |
| } |
| |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_get_previous_sibling( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| return om_node->prev_sibling; |
| } |
| |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_get_previous_sibling_element( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| axiom_node_t * result = axiom_node_get_previous_sibling( om_node, env ); |
| while ( result && axiom_node_get_node_type(result, env) != AXIOM_ELEMENT ) |
| result = axiom_node_get_previous_sibling( result, env ); |
| return result; |
| } |
| |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_get_next_sibling( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| int token = 0; |
| if(!om_node) |
| { |
| return NULL; |
| } |
| |
| /* we have to build the tree using stax builder if |
| * (1) om_node's next_sibling is not given (if available, we can just return that) |
| * (2) om_node is having a parent (otherwise, no concept of sibling) |
| * (3) om_node is having a stax builder (otherwise, it is a programatically built node) |
| * (4) parent is having a stax builder (otherwise, om_node is the only child, |
| * or sibling is programatically created) |
| * (5) parent is not yet fully built |
| */ |
| while((!om_node->next_sibling) && om_node->parent && om_node->parent->builder |
| && om_node->builder && (!axiom_node_is_complete(om_node->parent, env))) |
| { |
| token = axiom_stax_builder_next_with_token(om_node->builder, env); |
| if(token == -1) |
| { |
| return NULL; |
| } |
| } |
| |
| return om_node->next_sibling; |
| } |
| |
| AXIS2_EXTERN axiom_node_t *AXIS2_CALL |
| axiom_node_get_next_sibling_element( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| axiom_node_t * result = axiom_node_get_next_sibling( om_node, env ); |
| while ( result && axiom_node_get_node_type(result, env) != AXIOM_ELEMENT ) |
| result = axiom_node_get_next_sibling( result, env ); |
| return result; |
| } |
| |
| |
| AXIS2_EXTERN axiom_types_t AXIS2_CALL |
| axiom_node_get_node_type( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| return om_node->node_type; |
| } |
| |
| AXIS2_EXTERN axis2_bool_t AXIS2_CALL |
| axiom_node_is_complete( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| return om_node->done; |
| |
| } |
| |
| AXIS2_EXTERN struct axiom_document *AXIS2_CALL |
| axiom_node_get_document( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| if(om_node->builder) |
| { |
| return axiom_stax_builder_get_document(om_node->builder, env); |
| } |
| |
| return NULL; |
| } |
| |
| AXIS2_EXTERN void *AXIS2_CALL |
| axiom_node_get_data_element( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| return om_node->data_element; |
| } |
| |
| /** |
| internal function , not to be used by users |
| only sets the first_child link because this is needed by builder |
| */ |
| void AXIS2_CALL |
| axiom_node_set_first_child( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_node_t * first_child) |
| { |
| /** set the parent */ |
| axiom_node_set_parent(first_child, env, om_node); |
| om_node->first_child = first_child; |
| } |
| |
| /** |
| internal function not to be used by users |
| only sets the previous sibling link as it is needed by builders |
| |
| */ |
| void AXIS2_CALL |
| axiom_node_set_previous_sibling( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_node_t * prev_sibling) |
| { |
| om_node->prev_sibling = prev_sibling; |
| } |
| |
| /** |
| internal function, not to be used by users |
| only sets the next sibling link; |
| */ |
| void AXIS2_CALL |
| axiom_node_set_next_sibling( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_node_t * next_sibling) |
| { |
| om_node->next_sibling = next_sibling; |
| } |
| |
| /** |
| internal function not to be used by users |
| sets the node type only used in soap and om |
| */ |
| |
| axis2_status_t AXIS2_CALL |
| axiom_node_set_node_type( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_types_t type) |
| { |
| om_node->node_type = type; |
| return AXIS2_SUCCESS; |
| } |
| |
| /** |
| internal function , not to be used by users |
| only used in om and soap |
| */ |
| void AXIS2_CALL |
| axiom_node_set_data_element( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| void *data_element) |
| { |
| om_node->data_element = data_element; |
| } |
| |
| /** |
| internal function not to be used by users |
| only sets the build status |
| |
| */ |
| void AXIS2_CALL |
| axiom_node_set_complete( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axis2_bool_t done) |
| { |
| om_node->done = done; |
| } |
| |
| /** |
| internal function only sets the builder reference , |
| should not be used by user |
| */ |
| void AXIS2_CALL |
| axiom_node_set_builder( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| axiom_stax_builder_t * builder) |
| { |
| /* builder == NULL is a valid case */ |
| om_node->builder = builder; |
| } |
| |
| void AXIS2_CALL |
| axiom_node_assume_builder_ownership( |
| axiom_node_t *om_node, |
| const axutil_env_t * env) |
| { |
| om_node->own_builder = AXIS2_TRUE; |
| } |
| |
| AXIS2_EXTERN axis2_char_t *AXIS2_CALL |
| axiom_node_to_string( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| int status = AXIS2_SUCCESS; |
| axiom_output_t *om_output = NULL; |
| axiom_xml_writer_t *xml_writer = NULL; |
| axis2_char_t *xml = NULL; |
| AXIS2_ENV_CHECK(env, NULL); |
| AXIS2_PARAM_CHECK(env->error, om_node, NULL); |
| |
| xml_writer = axiom_xml_writer_create_for_memory(env, NULL, AXIS2_TRUE, 0, |
| AXIS2_XML_PARSER_TYPE_BUFFER); |
| if(!xml_writer) |
| { |
| return NULL; |
| } |
| |
| om_output = axiom_output_create(env, xml_writer); |
| if(!om_output) |
| { |
| axiom_xml_writer_free(xml_writer, env); |
| return NULL; |
| } |
| status = axiom_node_serialize(om_node, env, om_output); |
| if(status == AXIS2_SUCCESS) |
| { |
| xml = axutil_strdup(env, (axis2_char_t *)axiom_xml_writer_get_xml(xml_writer, env)); |
| } |
| axiom_output_free(om_output, env); |
| return xml; |
| } |
| |
| AXIS2_EXTERN axis2_char_t *AXIS2_CALL |
| axiom_node_sub_tree_to_string( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| int status = AXIS2_SUCCESS; |
| axiom_output_t *om_output = NULL; |
| axiom_xml_writer_t *xml_writer = NULL; |
| axis2_char_t *xml = NULL; |
| AXIS2_ENV_CHECK(env, NULL); |
| AXIS2_PARAM_CHECK(env->error, om_node, NULL); |
| |
| xml_writer = axiom_xml_writer_create_for_memory(env, NULL, AXIS2_TRUE, 0, |
| AXIS2_XML_PARSER_TYPE_BUFFER); |
| if(!xml_writer) |
| { |
| return NULL; |
| } |
| |
| om_output = axiom_output_create(env, xml_writer); |
| if(!om_output) |
| { |
| axiom_xml_writer_free(xml_writer, env); |
| return NULL; |
| } |
| status = axiom_node_serialize_sub_tree(om_node, env, om_output); |
| if(status == AXIS2_SUCCESS) |
| { |
| xml = axutil_strdup(env, (axis2_char_t *)axiom_xml_writer_get_xml(xml_writer, env)); |
| } |
| axiom_output_free(om_output, env); |
| return xml; |
| } |
| |
| AXIS2_EXTERN axis2_char_t *AXIS2_CALL |
| axiom_node_to_string_non_optimized( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| int status = AXIS2_SUCCESS; |
| axiom_output_t *om_output = NULL; |
| axiom_xml_writer_t *xml_writer = NULL; |
| axis2_char_t *xml = NULL; |
| AXIS2_ENV_CHECK(env, NULL); |
| AXIS2_PARAM_CHECK(env->error, om_node, NULL); |
| |
| xml_writer = axiom_xml_writer_create_for_memory(env, NULL, AXIS2_TRUE, 0, |
| AXIS2_XML_PARSER_TYPE_BUFFER); |
| if(!xml_writer) |
| { |
| return NULL; |
| } |
| |
| om_output = axiom_output_create(env, xml_writer); |
| if(!om_output) |
| { |
| axiom_xml_writer_free(xml_writer, env); |
| return NULL; |
| } |
| /*This is where we set the output to be non-optimized*/ |
| axiom_output_set_do_optimize(om_output, env, AXIS2_FALSE); |
| status = axiom_node_serialize(om_node, env, om_output); |
| if(status == AXIS2_SUCCESS) |
| { |
| xml = axutil_strdup(env, (axis2_char_t *)axiom_xml_writer_get_xml(xml_writer, env)); |
| } |
| axiom_output_free(om_output, env); |
| return xml; |
| } |
| |
| AXIS2_EXTERN axiom_node_t * AXIS2_CALL |
| axiom_node_add_sibling( |
| const axutil_env_t *env, |
| axiom_node_t *nodeElem, |
| axiom_node_t *nodeElemSibling) |
| { |
| assert(env != NULL); |
| |
| AXIS2_ENV_CHECK(env, NULL); |
| AXIS2_PARAM_CHECK(env->error, nodeElem, NULL); |
| AXIS2_PARAM_CHECK(env->error, nodeElemSibling, NULL); |
| |
| axiom_node_t *next_sib = NULL; |
| nodeElemSibling->parent = nodeElem->parent; |
| nodeElemSibling->prev_sibling = nodeElem; |
| next_sib = nodeElem->next_sibling; |
| if (next_sib) |
| { |
| next_sib->prev_sibling = nodeElemSibling; |
| } |
| nodeElemSibling->next_sibling = nodeElem->next_sibling; |
| nodeElem->next_sibling = nodeElemSibling; |
| |
| return nodeElem; |
| } |
| |
| #if 0 |
| |
| /** |
| internal function not to be used by users |
| only used by om builder |
| */ |
| AXIS2_EXTERN axis2_status_t AXIS2_CALL |
| axiom_node_set_document( |
| axiom_node_t * om_node, |
| const axutil_env_t * env, |
| struct axiom_document * om_doc) |
| { |
| /* om_doc == NULL is a valid case */ |
| om_node->om_doc = om_doc; |
| return AXIS2_SUCCESS; |
| } |
| |
| /** |
| * This is an internal function |
| */ |
| AXIS2_EXTERN axiom_stax_builder_t *AXIS2_CALL |
| axiom_node_get_builder( |
| axiom_node_t * om_node, |
| const axutil_env_t * env) |
| { |
| if(!om_node) |
| { |
| return NULL; |
| } |
| return om_node->builder; |
| } |
| |
| #endif |
| |