如何从C中的xml文件中解析/提取一些信息

时间:2013-03-11 20:05:31

标签: c xml-parsing

  

可能重复:
  XML Parser for C

你好 我需要一些关于如何使用C语言从XML文件中解析/提取信息的快速帮助。

我正在尝试的项目仅仅是为了个人学习。我正在努力学习C语言。我正在尝试编写一个程序,用于从预生成的XML配置文件中搜索spacefic文本或作者姓名。

下面是我的XML的副本:

 <?xml version="1.0" encoding="ISO-8859-1"?>
<config>
    <quote>
    <text>
        "Moral indignation is jealous with a halo."
    </text>
    <author>
        H.G. Wells
    </author>
    <livedfrom>
        1866-1946
    </livedfrom>
    <extrainfo />
</quote>

如果有人可以帮助我开始或指导我在线或教程阅读材料,我将不胜感激。

谢谢,

2 个答案:

答案 0 :(得分:0)

无论如何,这将归结为解析文本的艺术。您应该阅读正式的语法,并研究如何使用Flex和Bison构建一个简单的解析器。

否则,构建解析器的经典方法是使用一个前瞻标记来执行所谓的递归正确解析器。

然而,解析器总是与tokenizer串联工作。 tokenizer任务是将某些字符串转换为标记(通常实现为数值)。 tokes经常携带字符串(或从字符串生成的某个值(不是标记值),例如它生成的一些数字常量),因此解析器可以采取适当的操作。正则表达式通常用于告诉tokenizer将哪些字符串转换为什么标记。

再次回到递归的正确解析器。它本质上看起来像下面的代码。但请查看示例Wikipedia以获取更多信息。

void handle_token_foo()
{
  //Do something now when we know we handle token FOO
  ....
  //Find next token and take appropriate action
  Token t = tokenizer.get_next_token();
  if(t == TOKEN_TYPE_BAR)
  {
    parse_token_bar();  
  }
  else if(t == TOKEN_TYPE_FOO)
  {
    parse_token_foo();
  }
  else if(t == TOKEN_TYPE_END)
  {
     return;
  }
  throw ParseError();
  return 
}

void handle_token_bar()
{
  //Do something now when we know we handle token BAR
  ....
  //Find next token and take appropriate action

  Token t = tokenizer.get_next_token();
  if(t == TOKEN_TYPE_BAR)
  {
    parse_token_bar();  
  }
  else if(t == TOKEN_TYPE_FOO)
  {
    parse_token_foo();
  }
  else if(t == TOKEN_TYPE_END)
  {
     return;
  }
  throw ParseError();
  return;
}

“做某事”可能会推动堆栈上的值和运算符实现某种形式的Shunting yard algorithm。或者构建一个AST

然而,Boost boost::spirit中还有一个很好的库可用于构建解析器。

另一方面,如果你只是想要一个XML解析器,那么有很多现成的可供选择。已经在SO上看到了一些很好的流程图,它描述了根据您的要求,XML解析器很好。

答案 1 :(得分:0)

如果您对C ++感兴趣,可以尝试使用rapidxml:

http://rapidxml.sourceforge.net/
http://rapidxml.sourceforge.net/manual.html

在这里,我编写了一个解析和解析的示例代码。打印深度为三级(与您的一样)的xml内容:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "./rapidxml-1.13/rapidxml.hpp"
#include "./rapidxml-1.13/rapidxml_print.hpp"
#include <iostream>
#include <fstream>

using namespace std;
using namespace rapidxml;


void process_xml(const char* xml){
    xml_document<> doc;
    char text[strlen(xml)+1];
    strcpy(&text[0], xml);
    try{
        doc.parse<parse_default>(text);
    }
    catch(rapidxml::parse_error &ex){
        cout << "error: rapidxml::parse_error\n";
        return;
    }

    xml_node<> *ptr=NULL;
    try{
        if (doc.first_node()!=NULL){
            for (xml_node<> *node=doc.first_node(); node; node=node->next_sibling()){
                cout << "node->name: " << node->name() << endl;
                if (strcmp(node->name(), "")!=0){
                    xml_node<> *content_node = node->first_node();
                    ptr=content_node;
                    while ((content_node!=NULL) && (strcmp(content_node->name(), "")!=0)){
                        cout << "\t>>" << content_node->name() << endl;

                        for (xml_node<> *node_3rd=content_node->first_node(); node_3rd; node_3rd=node_3rd->next_sibling()){
                            cout << "name: " << node_3rd->name() << "; ";
                            cout << "value: " << node_3rd->value() << endl;
                        }

                        content_node=content_node->next_sibling();
                    }
                }
            }
            cout << "\n";
        }
    }
    catch(...){
        cout << "error: in reading an event!";
    }
}


int main(void){
    //read the xml from an input file
    std::ifstream ifs("in_file.txt");
    std::string xml;
    xml.assign(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());

    //process the xml
    process_xml(xml.c_str());

    return 0;
}
  • 注意:要将xml变为有效的xml,您必须关闭所有代码,因此最后应添加</config>,因为您在开头有<config>

要运行此代码,您必须从我提供的链接下载rapidxml并将其解压缩到项目文件夹中。编译不需要额外的标志。

然后,使用带有更正的xml的输入文件“in_file.txt”(*参见上面的通知),此代码将产生输出:

node->name: config
    >>quote
name: text; value: 
            "Moral indignation is jealous with a halo."

name: author; value: 
            H.G. Wells

name: livedfrom; value: 
            1866-1946

name: extrainfo; value: 

然后,您可以将结果值存储在变量,结构或任何您想要的内容中。