解释分析细致讲解一下这段代码int edit_config_internal(xmlDocPtr repo, xmlDocPtr edit, struct ncds_ds* ds, NC_EDIT_DEFOP_TYPE defop) { xmlXPathObjectPtr nodes; int i; char *msg = NULL; xmlNodePtr orig_node, edit_node, parent_node,model_node = NULL; keyList keys; xmlDocPtr model = ds->ext_model; DBG("%s BEGIN\n", __FILE__); keys = get_keynode_list(model); nodes = get_operation_elements(NC_EDIT_OP_REMOVE, edit); if (nodes != NULL) { if (!xmlXPathNodeSetIsEmpty(nodes->nodesetval)) { VERB("DELETE !xmlXPathNodeSetIsEmpty\n "); for (i = 0; i < nodes->nodesetval->nodeNr; i++) { edit_node = nodes->nodesetval->nodeTab[i]; model_node = find_element_model(edit_node, model); if (is_mandatory(model_node)) { ERROR("NC_ERR_DEL_MANDATORY_NOT_SUPPORT(%s:%d)\n",__FILE__, __LINE__); } orig_node = find_element_equiv(repo, edit_node, model, keys); for (; orig_node != NULL; orig_node = find_element_equiv(repo, edit_node, model, keys)) { parent_node = orig_node->parent; xmlUnlinkNode(orig_node); orig_node->parent = parent_node; edit_delete(orig_node); } edit_delete(edit_node); } } else { DBG("Delete xmlXPathNodeSetIsEmpty\n"); } xmlXPathFreeObject(nodes); } nodes = get_operation_elements(NC_EDIT_OP_REPLACE, edit); if (nodes != NULL) { if (!xmlXPathNodeSetIsEmpty(nodes->nodesetval)) { DBG("%s/%d something to replace nodeNr %d",__func__,__LINE__,nodes->nodesetval->nodeNr); for (i = 0; i < nodes->nodesetval->nodeNr; i++) { if (edit_replace_intrenal(repo, nodes->nodesetval->nodeTab[i], model, keys) != EXIT_SUCCESS) { xmlXPathFreeObject(nodes); goto error; } } } else { DBG("Replace xmlXPathNodeSetIsEmpty\n"); } xmlXPathFreeObject(nodes); } if (defop == NC_EDIT_DEFOP_MERGE) { if (edit->children != NULL) { if (edit_merge_intrenal(repo, edit->children, model, keys) != EXIT_SUCCESS) { goto error; } } } keyListFree(keys); return EXIT_SUCCESS; error: if (keys != NULL ) { keyListFree(keys); } return EXIT_FAILURE; }
时间: 2024-02-14 08:13:00 浏览: 86
xml.tar.gz_libxml2_linux c xml_linux xml
这段代码是一个 C 语言函数,主要作用是根据用户提交的 XML 文档,修改另一个 XML 文档中的元素节点。函数接受四个参数:
- xmlDocPtr repo:需要被修改的 XML 文档。
- xmlDocPtr edit:包含修改操作的 XML 文档。
- struct ncds_ds* ds:外部数据模型。
- NC_EDIT_DEFOP_TYPE defop:修改操作类型。
函数的返回值为 int 类型,表示执行结果,EXIT_SUCCESS 表示成功,EXIT_FAILURE 表示失败。
下面是函数的主要实现:
1. 获取关键节点列表
```c
keys = get_keynode_list(model);
```
该语句调用 get_keynode_list 函数获取外部数据模型中的关键节点列表,并将其赋值给变量 keys。
2. 删除操作
```c
nodes = get_operation_elements(NC_EDIT_OP_REMOVE, edit);
if (nodes != NULL) {
if (!xmlXPathNodeSetIsEmpty(nodes->nodesetval)) {
for (i = 0; i < nodes->nodesetval->nodeNr; i++) {
edit_node = nodes->nodesetval->nodeTab[i];
model_node = find_element_model(edit_node, model);
if (is_mandatory(model_node)) {
ERROR("NC_ERR_DEL_MANDATORY_NOT_SUPPORT(%s:%d)\n",__FILE__, __LINE__);
}
orig_node = find_element_equiv(repo, edit_node, model, keys);
for (; orig_node != NULL; orig_node = find_element_equiv(repo, edit_node, model, keys)) {
parent_node = orig_node->parent;
xmlUnlinkNode(orig_node);
orig_node->parent = parent_node;
edit_delete(orig_node);
}
edit_delete(edit_node);
}
}
xmlXPathFreeObject(nodes);
}
```
该语句首先调用 get_operation_elements 函数获取修改操作中所有的删除操作节点,并将其赋值给变量 nodes。然后,如果 nodes 不为空且 nodes 中的节点数不为零,则遍历 nodes 中的所有节点,依次执行以下操作:
- 从 edit_node 所在的数据模型中找到与之相等的模型节点,并将其赋值给变量 model_node。
- 如果 model_node 是必须存在的节点,则输出错误信息。
- 从 repo 文档中查找与 edit_node 相等的节点,并将其赋值给变量 orig_node。
- 如果 orig_node 不为空,则执行以下操作:
- 获取 orig_node 的父节点,将 orig_node 从原来的树形结构中删除。
- 将 orig_node 的父节点设置为 parent_node。
- 调用 edit_delete 函数删除 orig_node。
3. 替换操作
```c
nodes = get_operation_elements(NC_EDIT_OP_REPLACE, edit);
if (nodes != NULL) {
if (!xmlXPathNodeSetIsEmpty(nodes->nodesetval)) {
for (i = 0; i < nodes->nodesetval->nodeNr; i++) {
if (edit_replace_intrenal(repo, nodes->nodesetval->nodeTab[i], model, keys) != EXIT_SUCCESS) {
xmlXPathFreeObject(nodes);
goto error;
}
}
}
xmlXPathFreeObject(nodes);
}
```
该语句首先调用 get_operation_elements 函数获取修改操作中所有的替换操作节点,并将其赋值给变量 nodes。然后,如果 nodes 不为空且 nodes 中的节点数不为零,则遍历 nodes 中的所有节点,依次调用 edit_replace_intrenal 函数替换 XML 文档中的节点。
4. 合并操作
```c
if (defop == NC_EDIT_DEFOP_MERGE) {
if (edit->children != NULL) {
if (edit_merge_intrenal(repo, edit->children, model, keys) != EXIT_SUCCESS) {
goto error;
}
}
}
```
如果 defop 是 NC_EDIT_DEFOP_MERGE,表示需要执行合并操作。该语句首先判断 edit 文档是否包含子节点,如果包含,则调用 edit_merge_intrenal 函数合并 XML 文档中的节点。
5. 释放关键节点列表
```c
keyListFree(keys);
```
该语句调用 keyListFree 函数释放关键节点列表。
6. 错误处理
```c
error:
if (keys != NULL ) {
keyListFree(keys);
}
return EXIT_FAILURE;
```
如果在执行函数过程中出现错误,则跳转到 error 标签处执行错误处理代码。该代码首先释放关键节点列表,并返回 EXIT_FAILURE 表示执行失败。
阅读全文