2013-03-11 72 views
-1

可能重复:
XML Parser for C如何解析/用C提取一些信息出来的XML文件的

你好 我需要如何解析一些快速的帮助/提取信息在使用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> 

如果有人可以只帮我上手或直接我一些阅读材料在网上或教程中,我将不胜感激。

谢谢,

+1

http://www.xmlsoft.org/ – zzk 2013-03-11 20:07:34

+0

从处理XML文件开始学习C是相当有抱负的。购买一本好的C书并通过第一本书工作。 – 2013-03-11 20:08:54

+0

可能重复的[XML解析器的C](http://stackoverflow.com/questions/399704/xml-parser-for-c) – 2013-03-11 20:12:52

回答

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,并将它解压缩到项目文件夹中。编译不需要额外的标志。

然后,输入文件“in_file.txt”与您纠正XML(*请参阅上面的通知),该代码将产生作为输出:

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: 

然后,你可以得到的值存储在变量,结构或任何你想要的。

0

在任何情况下,这将归结为解析文本的艺术。你应该阅读正式的语法,也许看看如何使用Flex和Bison构建一个简单的解析器。

否则,构建解析器的经典方法是使用一个前视标记来做所谓的递归裁剪解析器。

然而,解析器总是与标记器协同工作。标记器任务是将某些字符串转换为标记(通常以数值形式实现)。 tokes经常带有字符串(或者是从字符串中产生的一些值(不是令牌值),例如某些数字常量),从而生成分析器可以采取适当的行动。正则表达式通常用于告诉标记器将哪个字符串转换为什么标记。

因此,再回到递归裁剪解析器。它的本质看起来像下面的代码。但请检查例如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解析器有一些现成的选择。在这里看到了一些很好的流程图,它描述了巫婆XML解析器根据您的需求是好的。