C libxml2 : 解析xmlPath循环遍历,提取孙节点参数。可能的?
C libxml2 : Parse xmlPath to traverse in a loop and extract parameters of grandchild nodes. Possible?
我是 Xpath 和 XML 的初学者。
我安装了 libxml2,我可以成功解析 XML 文件。
我还可以使用 xmlXPathContext 读取特定节点的值。
问题陈述和example.xml如下。
我在 shell 中实现了相同的功能,方法是 运行 为根的所有 children 设置一个 for 循环,即 Child 1,2,以及3 寻找匹配。然后我将 Child 的索引号存储在找到匹配项的位置。
对于这个特定的 child,为 GChild 提取 Param1 和 Param2 的值。
我们可以使用 xpath 运行 类似的循环吗?我们如何在循环中引用 Child ?
“Root/Child[i]/” ?
例如,
我得到输入为“ABCD2”。
然后我需要通过遍历所有 Child 1,2,3 来搜索“ABCD2”。
当我们知道匹配所在的是 Child 2 时,提取 Child 的特定 GChild 的 Param1 和 Param2,即 Child 的 GChild2 2.
也就是说,我们应该将“HIJK123”和“HIJK345”作为 2 个变量的输出。
example.xml
<Root>
<Child>
<GChild>
<Param> "ABCD1" </Param>
</GChild>
<GChild>
<Param> "EFGH123" </Param>
<Param> "EFGH345" </Param>
</GChild>
<GChild>
<Param> "IJKL123" </Param>
</GChild>
</Child>
<Child>
<GChild>
<Param> "ABCD2" </Param>
</GChild>
<GChild>
<Param> "HIJK123" </Param>
<Param> "HIJK345" </Param>
</GChild>
<GChild>
<Param> "LMNO123" </Param>
</GChild>
</Child>
<Child>
<GChild>
<Param1> "ABCD3" </Param1>
</GChild1>
<GChild>
<Param> "PQRS123" </Param>
<Param> "PQRS345" </Param>
</GChild>
<GChild>
<Param> "TUVW123" </Param>
</GChild>
</Child>
</Root>
如果您想要做的只是 return 任何在第一个 GChild 元素中包含 input-matching Param 节点的子元素的第二个 GChild 元素的所有 Param 节点,那么此 XPath 将工作:
//*/GChild[2]/Param[../../GChild[1]/Param[contains(text(),'ABCD2')]]
您可以在 http://xpather.com/DCioM5P4
尝试 XPath
下面是一些使用该 XPath 的示例代码,您的示例 XML 有效:
#include <libxml/xpath.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argc<2) return printf("Usage: %s <search_value>\n",argv[0]);
char xPath[100];
sprintf(xPath,"//*/GChild[2]/Param[../../GChild[1]/Param[contains(text(),'%s')]]",argv[1]);
char buffer[] = "<?xml version=\"1.0\"?>\n\
<Root>\n\
<Child>\n\
<GChild>\n\
<Param> \"ABCD1\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"EFGH123\" </Param>\n\
<Param> \"EFGH345\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"IJKL123\" </Param>\n\
</GChild>\n\
</Child>\n\
<Child>\n\
<GChild>\n\
<Param> \"ABCD2\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"HIJK123\" </Param>\n\
<Param> \"HIJK345\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"LMNO123\" </Param>\n\
</GChild>\n\
</Child>\n\
<Child>\n\
<GChild>\n\
<Param> \"ABCD3\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"PQRS123\" </Param>\n\
<Param> \"PQRS345\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"TUVW123\" </Param>\n\
</GChild>\n\
</Child>\n\
</Root>\n\
";
xmlDocPtr document = xmlParseDoc((xmlChar*)buffer);
xmlXPathContextPtr xPathCtx = xmlXPathNewContext(document);
xPathCtx->node = xmlDocGetRootElement(document);
xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression((xmlChar*)xPath, xPathCtx);
if(xpathObj == NULL){
printf("Failed to evaluate xpath\n");
}
xmlNodeSetPtr nodeset = xpathObj->nodesetval;
if(!xmlXPathNodeSetIsEmpty(nodeset)){
printf("Found nodes using: %s\n",xPath);
for(int i=0; i<xmlXPathNodeSetGetLength(nodeset); i++){
xmlNodePtr node = xmlXPathNodeSetItem(nodeset,i);
printf("<%s>%s</%s>\n",node->name,xmlNodeGetContent(node),node->name);
}
}else{
printf("Failed to find nodes using: %s\n",xPath);
}
xmlXPathFreeObject(xpathObj);
xmlXPathFreeContext(xPathCtx);
return 0;
}
我是 Xpath 和 XML 的初学者。 我安装了 libxml2,我可以成功解析 XML 文件。 我还可以使用 xmlXPathContext 读取特定节点的值。 问题陈述和example.xml如下。
我在 shell 中实现了相同的功能,方法是 运行 为根的所有 children 设置一个 for 循环,即 Child 1,2,以及3 寻找匹配。然后我将 Child 的索引号存储在找到匹配项的位置。 对于这个特定的 child,为 GChild 提取 Param1 和 Param2 的值。 我们可以使用 xpath 运行 类似的循环吗?我们如何在循环中引用 Child ? “Root/Child[i]/” ?
例如, 我得到输入为“ABCD2”。 然后我需要通过遍历所有 Child 1,2,3 来搜索“ABCD2”。 当我们知道匹配所在的是 Child 2 时,提取 Child 的特定 GChild 的 Param1 和 Param2,即 Child 的 GChild2 2. 也就是说,我们应该将“HIJK123”和“HIJK345”作为 2 个变量的输出。
example.xml
<Root>
<Child>
<GChild>
<Param> "ABCD1" </Param>
</GChild>
<GChild>
<Param> "EFGH123" </Param>
<Param> "EFGH345" </Param>
</GChild>
<GChild>
<Param> "IJKL123" </Param>
</GChild>
</Child>
<Child>
<GChild>
<Param> "ABCD2" </Param>
</GChild>
<GChild>
<Param> "HIJK123" </Param>
<Param> "HIJK345" </Param>
</GChild>
<GChild>
<Param> "LMNO123" </Param>
</GChild>
</Child>
<Child>
<GChild>
<Param1> "ABCD3" </Param1>
</GChild1>
<GChild>
<Param> "PQRS123" </Param>
<Param> "PQRS345" </Param>
</GChild>
<GChild>
<Param> "TUVW123" </Param>
</GChild>
</Child>
</Root>
如果您想要做的只是 return 任何在第一个 GChild 元素中包含 input-matching Param 节点的子元素的第二个 GChild 元素的所有 Param 节点,那么此 XPath 将工作:
//*/GChild[2]/Param[../../GChild[1]/Param[contains(text(),'ABCD2')]]
您可以在 http://xpather.com/DCioM5P4
尝试 XPath下面是一些使用该 XPath 的示例代码,您的示例 XML 有效:
#include <libxml/xpath.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argc<2) return printf("Usage: %s <search_value>\n",argv[0]);
char xPath[100];
sprintf(xPath,"//*/GChild[2]/Param[../../GChild[1]/Param[contains(text(),'%s')]]",argv[1]);
char buffer[] = "<?xml version=\"1.0\"?>\n\
<Root>\n\
<Child>\n\
<GChild>\n\
<Param> \"ABCD1\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"EFGH123\" </Param>\n\
<Param> \"EFGH345\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"IJKL123\" </Param>\n\
</GChild>\n\
</Child>\n\
<Child>\n\
<GChild>\n\
<Param> \"ABCD2\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"HIJK123\" </Param>\n\
<Param> \"HIJK345\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"LMNO123\" </Param>\n\
</GChild>\n\
</Child>\n\
<Child>\n\
<GChild>\n\
<Param> \"ABCD3\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"PQRS123\" </Param>\n\
<Param> \"PQRS345\" </Param>\n\
</GChild>\n\
<GChild>\n\
<Param> \"TUVW123\" </Param>\n\
</GChild>\n\
</Child>\n\
</Root>\n\
";
xmlDocPtr document = xmlParseDoc((xmlChar*)buffer);
xmlXPathContextPtr xPathCtx = xmlXPathNewContext(document);
xPathCtx->node = xmlDocGetRootElement(document);
xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression((xmlChar*)xPath, xPathCtx);
if(xpathObj == NULL){
printf("Failed to evaluate xpath\n");
}
xmlNodeSetPtr nodeset = xpathObj->nodesetval;
if(!xmlXPathNodeSetIsEmpty(nodeset)){
printf("Found nodes using: %s\n",xPath);
for(int i=0; i<xmlXPathNodeSetGetLength(nodeset); i++){
xmlNodePtr node = xmlXPathNodeSetItem(nodeset,i);
printf("<%s>%s</%s>\n",node->name,xmlNodeGetContent(node),node->name);
}
}else{
printf("Failed to find nodes using: %s\n",xPath);
}
xmlXPathFreeObject(xpathObj);
xmlXPathFreeContext(xPathCtx);
return 0;
}