/****************************************************************************** **函数名称: _xml_delete_empty **功 能: 删除无属性节、无孩子、无节点值的节点,同时返回下一个需要处理的节点(注: 不删属性节点) **输入参数: ** xml: XML树 **输出参数: NONE **返 回: 0:success !0:failed **实现描述: **注意事项: node节点必须为子节点,否则处理过程的判断条件会有错误!!! **作 者: # Qifeng.zou # 2013.10.21 # ******************************************************************************/ static xml_node_t *_xml_delete_empty(xml_tree_t *xml, Stack_t *stack, xml_node_t *node) { xml_node_t *parent, *prev; do { parent = node->parent; prev = parent->child; if (prev == node) { parent->child = node->next; xml_node_free_one(xml, node); /* 释放空节点 */ if (NULL != parent->child) { return parent->child; /* 处理子节点的兄弟节点 */ } /* 已无兄弟: 则处理父节点 */ xml_unset_child_flag(parent); /* 继续后续处理 */ } else { while (prev->next != node) { prev = prev->next; } prev->next = node->next; xml_node_free_one(xml, node); /* 释放空节点 */ if (NULL != prev->next) { return prev->next; /* 还有兄弟: 则处理后续节点 */ } else { /* 已无兄弟: 则处理父节点 */ if (xml_is_attr(prev)) { xml_unset_child_flag(parent); } /* 继续后续处理 */ } } /* 开始处理父节点 */ node = parent; stack_pop(stack); /* 删除无属性、无孩子、无节点值的节点 */ if (!xml_has_attr(node) && !xml_has_value(node) && !xml_has_child(node)) { continue; } if (NULL != node->next) { return node->next; /* 处理父节点的兄弟节点 */ } node = stack_pop(stack); } while(NULL != node); return NULL; }
/****************************************************************************** **函数名称: xml_delete_empty **功 能: 删除无属性节、无孩子、无节点值的节点(注: 不删属性节点) **输入参数: ** xml: XML树 **输出参数: NONE **返 回: 0:success !0:failed **实现描述: ** 1. 初始化栈 ** 2. 节点属性判断: **注意事项: ** 1. 属性节点不用入栈 ** 2. 用于孩子节点的节点需要入栈 ** 3. 如为无属性节点、无孩子节点、且无节点值的节点,则删除之 **作 者: # Qifeng.zou # 2013.10.21 # ******************************************************************************/ int xml_delete_empty(xml_tree_t *xml) { xml_node_t *node; Stack_t _stack, *stack = &_stack; if (stack_init(stack, XML_MAX_DEPTH)) { log_error(xml->log, "Init stack failed!"); return XML_ERR_STACK; } node = xml->root->child; while (NULL != node) { /* 1. 此节点为属性节点: 不用入栈, 继续查找其兄弟节点 */ if (xml_is_attr(node)) { if (NULL != node->next) { node = node->next; continue; } /* 属性节点后续无孩子节点: 说明其父节点无孩子节点, 此类父节点不应该入栈 */ log_error(xml->log, "Push is not right!"); return XML_ERR_STACK; } /* 2. 此节点有孩子节点: 入栈, 并处理其孩子节点 */ else if (xml_has_child(node)) { if (stack_push(stack, node)) { log_error(xml->log, "Push failed!"); return XML_ERR_STACK; } node = node->child; continue; } /* 3. 此节点为拥有节点值或属性节点, 而无孩子节点: 此节点不入栈, 并继续查找其兄弟节点 */ else if (xml_has_value(node) || xml_has_attr(node)) { do { /* 3.1 查找兄弟节点: 处理自己的兄弟节点 */ if (NULL != node->next) { node = node->next; break; } /* 3.2 已无兄弟节点: 则处理父节点的兄弟节点 */ node = stack_pop(stack); } while(1); continue; } /* 4. 删除无属性、无孩子、无节点值的节点 */ else { /* if (!xml_has_attr(node) && !xml_has_child(node) && !xml_has_value(node) && !xml_is_attr(node)) */ node = _xml_delete_empty(xml, stack, node); } } stack_destroy(stack); return XML_OK; }
/****************************************************************************** **函数名称: _xml_node_len **功 能: 计算节点打印成XML格式字串时的长度(注: XML有层次结构) **输入参数: ** root: XML树根节点 ** stack: 栈 **输出参数: **返 回: 节点及其属性、孩子节点的总长度 **实现描述: **注意事项: **作 者: # Qifeng.zou # 2013.06.10 # ******************************************************************************/ int _xml_node_len(xml_tree_t *xml, xml_node_t *root, Stack_t *stack) { int depth, len; xml_node_t *node = root; depth = stack_depth(stack); if (0 != depth) { log_error(xml->log, "Stack depth must empty. depth:[%d]", depth); return XML_ERR_STACK; } len = 0; do { /* 1. 将要处理的节点压栈 */ node->temp = node->child; if (stack_push(stack, node)) { log_error(xml->log, "Stack push failed!"); return XML_ERR_STACK; } /* 2. 打印节点名 */ depth = stack_depth(stack); xml_node_name_len(node, depth, len); /* 3. 打印属性节点 */ if (xml_has_attr(node)) { xml_node_attr_len(node, len); } /* 4. 打印节点值 */ xml_node_value_len(node, len); /* 5. 选择下一个处理的节点: 从父亲节点、兄弟节点、孩子节点中 */ node = xml_node_next_len(xml, stack, node, &len); }while (NULL != node); if (!stack_empty(stack)) { return XML_ERR_STACK; } return len; }
/****************************************************************************** **函数名称: xml_add_attr **功 能: 往节点中添加属性节点 **输入参数: ** node: 需要添加属性节点的节点 ** attr: 属性节点(链表或单个节点) **输出参数: **返 回: 被创建节点的地址 **实现描述: 属性节点放在所有属性节点后面 **注意事项: 属性节点(attr)可以有兄弟节点 **作 者: # Qifeng.zou # 2013.03.01 # ******************************************************************************/ xml_node_t *xml_add_attr( xml_tree_t *xml, xml_node_t *node, const char *name, const char *value) { xml_node_t *attr, *parent = node->parent, *link = node->child; if (NULL == parent) { log_error(xml->log, "Please create root node at first!"); return NULL; } if (xml_is_attr(node)) { log_error(xml->log, "Can't add attr for attribute node!"); return NULL; } /* 1. 创建节点 */ attr = xml_node_creat_ext(xml, XML_NODE_ATTR, name, value); if (NULL == attr) { log_error(xml->log, "Create node failed!"); return NULL; } /* 2. 将节点放入XML树 */ if (NULL == link) { /* 没有孩子节点,也没有属性节点 */ node->child = attr; node->tail = attr; attr->parent = node; xml_set_attr_flag(node); return attr; } if (xml_has_attr(node)) { /* 有属性节点 */ if (xml_is_attr(node->tail)) { /* 所有子节点也为属性节点时,attr直接链入链表尾 */ attr->parent = node; node->tail->next = attr; node->tail = attr; xml_set_attr_flag(node); return attr; } while ((NULL != link->next) /* 查找最后一个属性节点 */ &&(xml_is_attr(link->next))) { link = link->next; } attr->parent = node; attr->next = link->next; link->next = attr; xml_set_attr_flag(node); return attr; } else if (xml_has_child(node) && !xml_has_attr(node)) { /* 有孩子但无属性 */ attr->parent = node; attr->next = node->child; node->child = attr; xml_set_attr_flag(node); return attr; } xml_node_free_one(xml, attr); log_error(xml->log, "Add attr node failed!"); return NULL; }