C libxml2 :解析 xmlPath 以循环遍历并提取孙节点的参数。可能的?

发布于 2025-01-10 22:55:48 字数 1819 浏览 0 评论 0原文

我是使用 Xpath 和 XML 的初学者。 我已经安装了 libxml2 并且可以成功解析 XML 文件。 我还可以使用 xmlXPathContext 读取特定节点的值。 问题陈述和example.xml如下。

我在 shell 中实现了相同的功能,方法是为 Root 的所有子级(即 Child 1,2 和 3)运行 for 循环来查找匹配项。然后我存储找到匹配项的 Child 的索引号。 对于此特定子项,提取 GChild 的 Param1 和 Param2 值。 我们可以使用 xpath 运行类似的循环吗?我们如何在循环中引用Child? “根/子[i]/”?

例如, 我得到的输入为“ABCD2”。 然后我需要通过遍历所有 Child 1,2,3 来搜索“ABCD2”。 当我们知道匹配所在的是 Child 2 时,提取 Child 的特定 GChild 的 Param1 和 Param2,即 Child2 的 GChild2。 也就是说,我们应该得到“HIJK123”和“HIJK345”作为两个变量的输出。

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>

I am a beginner in using Xpath and XML.
I have libxml2 installed and I can parse the XML file successfully.
I can also read value of a particular node by using xmlXPathContext.
The problem statement and example.xml is as below.

I have implemented the same functionality in shell by running a for loop for all children of Root that is, Child 1,2, and 3 to find the match. Then I store the index# of Child where match is found.
For this particular child, extract values for Param1 and Param2 for the GChild.
Can we run similar loop using xpath? How do we reference the Child in a loop?
"Root/Child[i]/" ?

For example,
I get input as "ABCD2".
Then I need to search for "ABCD2" by traversing through all Child 1,2,3.
When we know it is Child 2 where the match lies, extract the Param1 and Param2 of that particular GChild of Child i.e GChild2 of Child2.
That is, we should get "HIJK123"" and "HIJK345" as output in 2 variables.

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

自由如风 2025-01-17 22:55:48

如果您想要做的只是从第一个 GChild 元素中包含输入匹配 Param 节点的任何 Child 的第二个 GChild 元素返回所有 Param 节点,则此 XPath 将起作用:

//*/GChild[2]/Param[../../GChild[1]/Param[contains(text(),'ABCD2')]]

您可以尝试位于 http://xpather.com/DCioM5P4

这是使用该 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;
}

If all you want to do is to return all the Param nodes from the second GChild element of any Child that contains an input-matching Param node in the first GChild element, then this XPath will work:

//*/GChild[2]/Param[../../GChild[1]/Param[contains(text(),'ABCD2')]]

You can try the XPath at http://xpather.com/DCioM5P4

Here is some sample code using that XPath and your sample XML that works:

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文