如何使用带有libxml2库的C查找XML文件中特定标签的出现?

问题描述

<?xml version='1.0' encoding='utf-8'?>
<UnlimitRectCubes>
    <RectCubes>
        <depth>0</depth>
        <rectangle>
            <height>0</height>
            <width>0</width>
        </rectangle>
    </RectCubes>
    <RectCubes>
        <depth>1</depth>
        <rectangle>
            <height>11</height>
            <width>101</width>
        </rectangle>
    </RectCubes>
    <RectCubes>
        <depth>2</depth>
        <rectangle>
            <height>22</height>
            <width>202</width>
        </rectangle>
    </RectCubes>
</UnlimitRectCubes>

注意:我还包括了.xml文件

void print_element_names(xmlNode *a_node,char **findStr)
{
    xmlNode *cur_node = NULL;
    char *key = *findStr;
    cur_node = a_node;
    int len = 0;

while (cur_node)
{
 if ((!xmlStrcmp(cur_node->name,(const xmlChar *)key)))
    {
        len++; //len is int type
    }
  cur_node = cur_node->next;
}
  printf("%d",len);
   //int i = 0;
//xmlChar *array = (xmlChar *)calloc(1,sizeof(xmlChar));
for (cur_node = a_node; cur_node; cur_node = cur_node->next)
{
    if ((cur_node->type == XML_ELEMENT_NODE))
    {
        if ((!xmlStrcmp(cur_node->name,(const xmlChar *)key)))
        {
            //printf("%s",cur_node->children->content);
        }
    }
    print_element_names(cur_node->children,findStr);
}
}

int main(int argc,char **argv)
{
    xmlDoc *doc = NULL;           /* an xml document */
    xmlNode *root_element = NULL; /* a node in a xml tree */
    if (argc != 2)
    {
        return (1);
    }
    LIBXML_TEST_VERSION
    /*  parse the file and get the DOM */
    doc = xmlReadFile(argv[1],NULL,0);
    if (doc == NULL)
    {
        printf("error Could not parse");
        return;
    }
    /*Get the root element*/
    root_element = xmlDocgetRootElement(doc);
    char *myStr = "depth";
    print_element_names(root_element,&myStr);

    xmlFreeDoc(doc);

    /*
        *free the global variables that may have been allocated by the     parser
    */
    xmlCleanupParser();

    return 0;
}

输出:0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

我需要找到.xml文件中特定标签的出现频率,在这里我已将其作为键(char *)传递给函数,并使用xmlStrCmp()来验证正确的标签

该len应该打印整数值,但似乎输出以下内容:请参考上面的输出。实际出现3个特定标签,并且输出show具有3个1。 我相信,我没有正确地遍历XML树,正确的方法是什么?还是有任何XML函数可实现这一目标?

输入:.xml文件和感兴趣的标记作为键传递 预期输出标签出现的次数在这种情况下,我应该得到3。

for (cur_node = a_node; cur_node; cur_node = cur_node->next)
{
    if ((cur_node->type == XML_ELEMENT_NODE))
    {
        if ((!xmlStrcmp(cur_node->children->name,(const xmlChar *)key)))
        {
            //printf("%s\n",cur_node->children->content);
        }
         printf("%s",cur_node->name);   
 }
    
    len += print_element_names(cur_node->children,findStr);
}
printf("%d ",len);

更新的输出: UnlimitRectCubes0 RectCubes0深度0 2 0矩形0高度0 2 0宽度0 2 0 10 0 11 0 RectCubes0深度0 2 0矩形0高度0 2 0宽度0 2 0 10 0 11 0 RectCubes0深度0 2 0矩形0高度0 2 0宽度0 2 0 10 0 11 0 17 3 >

解决方法

您不会将找到的标签的数量在一个级别上传播到呼叫级别。

我尝试了这段代码并获得了正确的结果:

/*
 * Compile with:
 * > gcc `xml2-config --cflags` -std=c99 -o test  test.c `xml2-config --libs`
 * */
 
#include <stdio.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>

int print_element_names(xmlNode *a_node,char **findStr)
{
    xmlNode *cur_node = a_node;
    char *key = *findStr;
    int len = 0;

    if (a_node == NULL)
        return 0;
    
    printf("a_node->name=%s\n",a_node->name);
    while (cur_node)
    {
        printf("cur_node->name=%s,type=%d\n",cur_node->name,cur_node->type);
        if ((!xmlStrcmp(cur_node->name,(const xmlChar *)key)))
        {
            len++; //len is int type
        }
        cur_node = cur_node->next;
    }
    printf("found=%d\n",len);

    for (cur_node = a_node; cur_node; cur_node = cur_node->next)
    {
        if ((cur_node->type == XML_ELEMENT_NODE))
        {
    
            printf("search children for cur_node->name=%s,cur_node->type);
            len += print_element_names(cur_node->children,findStr);
        }
    }
    printf("found total for a_node->name %s: %d\n",a_node->name,len);
    return len;
}

int main(int argc,char **argv)
{
    xmlDoc *doc = NULL;           /* an xml document */
    xmlNode *root_element = NULL; /* a node in a xml tree */

    LIBXML_TEST_VERSION
    /*  parse the file and get the DOM */
    doc = xmlReadFile("test.xml",NULL,0);
    if (doc == NULL)
    {
        printf("error could not parse");
        return 1;
    }
    /*Get the root element*/
    root_element = xmlDocGetRootElement(doc);
    char *myStr = "depth";
    print_element_names(root_element,&myStr);

    xmlFreeDoc(doc);
    xmlCleanupParser();

    return 0;
}