/****************************************************************************** **函数名称: _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; }
static int medin_doconvert( xml *node, fields *info, xml_convert *c, int nc, int *found ) { int i, fstatus; char *d; *found = 0; if ( !xml_has_value( node ) ) return BIBL_OK; d = xml_value_cstr( node ); for ( i=0; i<nc && *found==0; ++i ) { if ( c[i].a==NULL ) { if ( xml_tag_matches( node, c[i].in ) ) { *found = 1; fstatus = fields_add( info, c[i].out, d, c[i].level ); if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; } } else { if ( xml_tag_has_attribute( node, c[i].in, c[i].a, c[i].aval ) ) { *found = 1; fstatus = fields_add( info, c[i].out, d, c[i].level ); if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; } } } return BIBL_OK; }
/****************************************************************************** **函数名称: 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; }
/* <ArticleTitle>Mechanism and.....</ArticleTitle> */ static int medin_articletitle( xml *node, fields *info ) { int fstatus, status = BIBL_OK; if ( xml_has_value( node ) ) { fstatus = fields_add( info, "TITLE", xml_value_cstr( node ), 0 ); if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR; } return status; }
/****************************************************************************** **函数名称: xml_add_child **功 能: 给指定节点添加孩子节点 **输入参数: ** node: 需要添加孩子节点的节点 ** name: 孩子节点名 ** value: 孩子节点值 **输出参数: **返 回: 新增节点的地址 **实现描述: **注意事项: ** 1. 新建孩子节点 ** 2. 将孩子加入子节点链表尾 **作 者: # Qifeng.zou # 2013.03.01 # ******************************************************************************/ xml_node_t *xml_add_child(xml_tree_t *xml, xml_node_t *node, const char *name, const char *value) { xml_node_t *child = NULL; if (xml_is_attr(node)) { log_error(xml->log, "Can't add child for attribute node![%s]", node->name.str); return NULL; } #if defined(__XML_EITHER_CHILD_OR_VALUE__) else if (xml_has_value(node)) { log_error(xml->log, "Can't add child for the node which has value![%s]", node->name.str); return NULL; } #endif /*__XML_EITHER_CHILD_OR_VALUE__*/ /* 1. 新建孩子节点 */ child = xml_node_creat_ext(xml, XML_NODE_CHILD, name, value); if (NULL == child) { log_error(xml->log, "Create node failed![%s]", name); return NULL; } child->parent = node; /* 2. 将孩子加入子节点链表尾 */ if (NULL == node->tail) { /* 没有孩子&属性节点 */ node->child = child; } else { node->tail->next = child; } node->tail = child; xml_set_child_flag(node); return child; }
/* <Journal> * <ISSN>0027-8424</ISSN> * <JournalIssue PrintYN="Y"> * <Volume>100</Volume> * <Issue>21</Issue> * <PubDate> * <Year>2003</Year> * <Month>Oct</Month> * <Day>14</Day> * </PubDate> * </Journal Issue> * </Journal> * * or.... * * <Journal> * <ISSN IssnType="Print">0735-0414</ISSN> * <JournalIssue CitedMedium="Print"> * <Volume>38</Volume> * <Issue>1</Issue> * <PubDate> * <MedlineDate>2003 Jan-Feb</MedlineDate> * </PubDate> * </JournalIssue> * <Title>Alcohol and alcoholism (Oxford, Oxfordshire) </Title> * <ISOAbbreviation>Alcohol Alcohol.</ISOAbbreviation> * </Journal> */ static int medin_journal1( xml *node, fields *info ) { xml_convert c[] = { { "Title", NULL, NULL, "TITLE", 1 }, { "ISOAbbreviation", NULL, NULL, "SHORTTITLE", 1 }, { "ISSN", NULL, NULL, "ISSN", 1 }, { "Volume", NULL, NULL, "VOLUME", 1 }, { "Issue", NULL, NULL, "ISSUE", 1 }, { "Year", NULL, NULL, "PARTDATE:YEAR", 1 }, { "Month", NULL, NULL, "PARTDATE:MONTH", 1 }, { "Day", NULL, NULL, "PARTDATE:DAY", 1 }, }; int nc = sizeof( c ) / sizeof( c[0] ), status, found; if ( xml_has_value( node ) ) { status = medin_doconvert( node, info, c, nc, &found ); if ( status!=BIBL_OK ) return status; if ( !found ) { if ( xml_tag_matches( node, "MedlineDate" ) ) { status = medin_medlinedate( info, xml_value_cstr( node ), 1 ); if ( status!=BIBL_OK ) return status; } if ( xml_tag_matches( node, "Language" ) ) { status = medin_language( node, info, 1 ); if ( status!=BIBL_OK ) return status; } } } if ( node->down ) { status = medin_journal1( node->down, info ); if ( status!=BIBL_OK ) return status; } if ( node->next ) { status = medin_journal1( node->next, info ); if ( status!=BIBL_OK ) return status; } return BIBL_OK; }