/* * 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 #include #include #include #include #include #include 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); } om_node->parent = NULL; om_node->prev_sibling = NULL; om_node->next_sibling = NULL; om_node->builder = 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; } #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