如何使用libxml2更深入地解析xml文件

时间:2017-03-16 19:19:12

标签: c xml parsing libxml2

我在深入解析xml文件方面遇到了问题。为了简单起见,我们假设我有xml文件结构,在xmlsoft.org中提供:

<?xml version="1.0"?>
<story>
  <storyinfo>
    <author>John Fleck</author>
    <datewritten>June 2, 2002</datewritten>
    <keyword>example keyword</keyword>
  </storyinfo>
  <body>
    <headline>This is the headline</headline>
    <para>This is the body text.</para>
  </body>
</story>

为了从xml的相似文件中检索每个关键字,开发人员会使用此解决方案:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

void
parseStory (xmlDocPtr doc, xmlNodePtr cur) {

    xmlChar *key;
    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
        if ((!xmlStrcmp(cur->name, (const xmlChar *)"keyword"))) {
            key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
            printf("keyword: %s\n", key);
            xmlFree(key);
        }
    cur = cur->next;
    }
    return;
}

static void
parseDoc(char *docname) {

    xmlDocPtr doc;
    xmlNodePtr cur;

    doc = xmlParseFile(docname);

    if (doc == NULL ) {
        fprintf(stderr,"Document not parsed successfully. \n");
        return;
    }

    cur = xmlDocGetRootElement(doc);

    if (cur == NULL) {
        fprintf(stderr,"empty document\n");
        xmlFreeDoc(doc);
        return;
    }

    if (xmlStrcmp(cur->name, (const xmlChar *) "story")) {
        fprintf(stderr,"document of the wrong type, root node != story");
        xmlFreeDoc(doc);
        return;
    }

    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
        if ((!xmlStrcmp(cur->name, (const xmlChar *)"storyinfo"))){
            parseStory (doc, cur);
        }

    cur = cur->next;
    }

    xmlFreeDoc(doc);
    return;
}

int
main(int argc, char **argv) {

    char *docname;

    if (argc <= 1) {
        printf("Usage: %s docname\n", argv[0]);
        return(0);
    }

    docname = argv[1];
    parseDoc (docname);

    return (1);
}

我的疑问是:例如,如果<storyinfo>有另一个属性,如

<storyinfo>
...
    <rev>
        <id> 26546 </id>  
    </rev>
</storyinfo>

我如何从<id>访问/ printf(例如)<rev>?再说一次,我怎么能越来越深入地得到我想要的东西?对于上面的例子,我尝试了,没有成功:

在xmlFreeDoc(doc)行之前在parseDoc函数上添加此内容

cur = cur->xmlChildrenNode;
    while (cur != NULL) {
        if ((!xmlStrcmp(cur->name, (const xmlChar *)"rev"))){
            parseRev (doc, cur);
        }

    cur = cur->next;
    }

创建一个新函数parseRev(xmlDocPtr doc,xmlNodePtr cur):

void
parseRev (xmlDocPtr doc, xmlNodePtr cur) {

    xmlChar *key;
    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
        if ((!xmlStrcmp(cur->name, (const xmlChar *)"id"))) {
            key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
            printf("id: %s\n", key);
            xmlFree(key);
        }
    cur = cur->next;
    }
    return;
}

我该如何做到这一点?

1 个答案:

答案 0 :(得分:0)

似乎缺少的重要细节:当您通过执行以下cur-&gt;下一次迭代每个孩子时,它只使用IMMEDIATE子项。对子项story进行迭代将为您提供storyinfostorybody,而不会为您提供任何其他内容。

  

在xmlFreeDoc(doc)行

之前在parseDoc函数上添加它

您不希望在parseDoc中执行此操作,因为rev位于storyinfo内。当您迭代storyinfo的子项时,添加此检查,它应该可以正常工作。