libxml2 解析来自不同父节点的相似节点
libxml2 parse similar nodes from different parent nodes
我有一个具有以下结构的 XML 文件(针对此问题进行了简化):
<SuperNode>
<MediumNode Enable="YES">
<Child attr1="1" />
<Child attr1="2" />
<Child attr1="3" />
</MediumNode>
<MediumNode Enable="YES">
<Child attr1="4" />
<Child attr1="5" />
</MediumNode>
</SuperNode>
我使用以下逻辑在 C 中用 libxml2 解析它(为简单起见省略了错误检查),我从他们的 website 的 libxml2 示例中获取了这个逻辑。我需要遍历所有“MediumNode”节点的“Child”节点的所有属性:
xmlDocPtr doc = xmlParseFile("/path/to/xml"); /* check for errors */
xmlXPathContextPtr ctx = xmlXPathNewContext(doc); /* check for errors */
xmlXPathObjectPtr obj = xmlXPathEvalExpression("/*/*[@Enable=\"YES\"]/Child", ctx); /* check for errors */
xmlXPathNodeSetIsEmpty(obj->nodesetval); /* check for errors */
int n_nodes = obj->nodesetval->nodeNr; /* this is correctly identified as 5 */
xmlNodePtr node = obj->nodesetval->nodeTab[0]; /* list of parsed Child nodes */
xmlAttrPtr attr = NULL;
for (int i = 0; i < n_nodes; i++) {
attr = xmlGetProp(node, "attr1"); /* correctly gets the attribute value */
/* process attribute info */
xmlFree(attr);
node = node->next;
}
xmlXPathFreeObject(obj); /* cleanup code */
xmlFreeDoc(doc);
xmlCleanupParser();
现在,上述逻辑中的“n_nodes”变量正确识别了所有“MediumNode”节点中“Child”节点的数量(实际XML文件有几个MediumNode节点) .但是当 for 循环开始时,它在仅从第一个“MediumNode”节点解析出“Child”节点后崩溃。在上述情况下,它将在第一个“MediumNode”的 3 个节点后崩溃。我写的逻辑有什么错误吗?请随意指出。我已经在这里待了 2 天了。
哦,使用的 xpath 在命令行上使用 xmlstarlet 二进制文件进行验证:
xmlstarlet sel -t -c "/*/*[@Enable=\"YES\"]/Child" /path/to/xml
这会正确输出所有五个“子”节点。
我在自定义嵌入式 Linux 3.2.0、libc 2.13、libxml2 2.8.0
上执行此操作
谢谢。
对您的代码稍作改动即可运行。
xmlDocPtr doc = xmlParseFile("/path/to/xml"); /* check for errors */
xmlXPathContextPtr ctx = xmlXPathNewContext(doc); /* check for errors */
xmlXPathObjPtr obj = xmlXPathEvalExpression("/*/*[@Enable=\"YES\"]/Child", ctx); /* check for errors */
xmlXPathNodeSetIsEmpty(obj->nodesetval); /* check for errors */
int n_nodes = obj->nodesetval->nodeNr; /* this is correctly identified as 5 */
xmlNodePtr node;
xmlAttrPtr attr = NULL;
for (int i = 0; i < n_nodes; i++) {
node = obj->nodesetval->nodeTab[i]; /* gets the ith child node
attr = xmlGetProp(node, "attr1"); /* correctly gets the attribute value for ith node*/
/* process attribute info */
printf("found attr1=%s\n", attr);
xmlFree(attr);
// node = node->next;
}
xmlXPathFreePbject(obj); /* cleanup code */
xmlFreeDoc(doc);
xmlCleanupParser();
上面代码的调试输出是这样的:
found attr1=1
found attr1=2
found attr1=3
found attr1=4
found attr1=5
对于您的代码,问题出在 for 循环中 - 而不是您的 xpath。如果您在循环中打印属性值,您将看到它在每个正确的属性后打印 (null)。你代码的调试输出是这样的:
found attr1=1
found attr1=(null)
found attr1=2
found attr1=(null)
found attr1=3
我有一个具有以下结构的 XML 文件(针对此问题进行了简化):
<SuperNode>
<MediumNode Enable="YES">
<Child attr1="1" />
<Child attr1="2" />
<Child attr1="3" />
</MediumNode>
<MediumNode Enable="YES">
<Child attr1="4" />
<Child attr1="5" />
</MediumNode>
</SuperNode>
我使用以下逻辑在 C 中用 libxml2 解析它(为简单起见省略了错误检查),我从他们的 website 的 libxml2 示例中获取了这个逻辑。我需要遍历所有“MediumNode”节点的“Child”节点的所有属性:
xmlDocPtr doc = xmlParseFile("/path/to/xml"); /* check for errors */
xmlXPathContextPtr ctx = xmlXPathNewContext(doc); /* check for errors */
xmlXPathObjectPtr obj = xmlXPathEvalExpression("/*/*[@Enable=\"YES\"]/Child", ctx); /* check for errors */
xmlXPathNodeSetIsEmpty(obj->nodesetval); /* check for errors */
int n_nodes = obj->nodesetval->nodeNr; /* this is correctly identified as 5 */
xmlNodePtr node = obj->nodesetval->nodeTab[0]; /* list of parsed Child nodes */
xmlAttrPtr attr = NULL;
for (int i = 0; i < n_nodes; i++) {
attr = xmlGetProp(node, "attr1"); /* correctly gets the attribute value */
/* process attribute info */
xmlFree(attr);
node = node->next;
}
xmlXPathFreeObject(obj); /* cleanup code */
xmlFreeDoc(doc);
xmlCleanupParser();
现在,上述逻辑中的“n_nodes”变量正确识别了所有“MediumNode”节点中“Child”节点的数量(实际XML文件有几个MediumNode节点) .但是当 for 循环开始时,它在仅从第一个“MediumNode”节点解析出“Child”节点后崩溃。在上述情况下,它将在第一个“MediumNode”的 3 个节点后崩溃。我写的逻辑有什么错误吗?请随意指出。我已经在这里待了 2 天了。 哦,使用的 xpath 在命令行上使用 xmlstarlet 二进制文件进行验证:
xmlstarlet sel -t -c "/*/*[@Enable=\"YES\"]/Child" /path/to/xml
这会正确输出所有五个“子”节点。 我在自定义嵌入式 Linux 3.2.0、libc 2.13、libxml2 2.8.0
上执行此操作谢谢。
对您的代码稍作改动即可运行。
xmlDocPtr doc = xmlParseFile("/path/to/xml"); /* check for errors */
xmlXPathContextPtr ctx = xmlXPathNewContext(doc); /* check for errors */
xmlXPathObjPtr obj = xmlXPathEvalExpression("/*/*[@Enable=\"YES\"]/Child", ctx); /* check for errors */
xmlXPathNodeSetIsEmpty(obj->nodesetval); /* check for errors */
int n_nodes = obj->nodesetval->nodeNr; /* this is correctly identified as 5 */
xmlNodePtr node;
xmlAttrPtr attr = NULL;
for (int i = 0; i < n_nodes; i++) {
node = obj->nodesetval->nodeTab[i]; /* gets the ith child node
attr = xmlGetProp(node, "attr1"); /* correctly gets the attribute value for ith node*/
/* process attribute info */
printf("found attr1=%s\n", attr);
xmlFree(attr);
// node = node->next;
}
xmlXPathFreePbject(obj); /* cleanup code */
xmlFreeDoc(doc);
xmlCleanupParser();
上面代码的调试输出是这样的:
found attr1=1
found attr1=2
found attr1=3
found attr1=4
found attr1=5
对于您的代码,问题出在 for 循环中 - 而不是您的 xpath。如果您在循环中打印属性值,您将看到它在每个正确的属性后打印 (null)。你代码的调试输出是这样的:
found attr1=1
found attr1=(null)
found attr1=2
found attr1=(null)
found attr1=3