QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1169|回复: 3

用c写了一个从xml中提取数据的代码

[复制链接]
发表于 2005-3-5 19:36:07 | 显示全部楼层 |阅读模式
我的最初目的是想把它用在CGI程序中从xml文件里读取数据,但后来根本没把它派上用场.
把它放上来,希望能够有用,至少算法能对大家有帮助。

    readme-zh.txt:

    Cxmlread library
    2004-12-11
    neptune_ning
    email:[email protected]

    =====
    简介
    =====
            这是一个用C语言写的库。我的最初目的是把它用在CGI程序中从xml文件里读取数据。所以我尽量使它简洁快速。
            它不会像Dom一样把所有节点读进内存再处理,它只会读你所需要的元素,其他将会被忽略,所以它较Dom高效。

    +++++++++
    版权问题
    +++++++++
            你可以自由使用修改发布引用,不受任何限制。
            这是原创代码,不在任何协议之下。

    ++++++++++++++++
    包含的文件:
    ++++++++++++++++

    xmlread.h --头文件
    interface.c --用户界面
    readfile.c --文档读取和数据处理
    structure.c --结构

    readme-zh.txt --你现在读的这个文件
    readme-en.txt
    example.c & example.xml -- 一个范例程序,旨在测试容错性。

    +++++++++++++
    主要函数和结构
    +++++++++++++++
    "NODE" 描述一个xml元素节点
    "struct attribute" 描述元素的属性
    "struct result" 包含在NODE结构中,是一个链表结构,用来保存返回值。最后一个的next指针为NULL.

    以下是结构声明(structure.c):

    struct result{
            char *value;
            struct result *next;
    };
    struct attribute
    {
    char *name;
    int array_size; //result 链表的长度.
    struct result *result;
    };

    typedef struct node
    {
      int needvalue;
      int array_size; //result 链表的长度.
      char *name;
      struct result *result;
      struct attribute **attr;
      struct node *brother; //同级的兄弟节点
      struct node *head; //指向同一级节点的头一个,方便在它们当中搜索
      struct node *child; //下级节点
      int attrnum;
    }NODE;
    ---------------
    fuction: NODE *xml_init(); (interface.c)
            初始化一个树结构,返回其指针。

    fuction: NODE *getnodevalue(char *,NODE *); (interface.c)
            要求取得元素的值,参数1是元素在xml文档中的路径。同Unix中的文件路径类似,如果你了解Xpath就很容易理解。参数2是树指针。
            返回节点指针,方便对结果进行处理。
    例:name=getnodevalue("/root/project/name",tree);
           
    fuction: NODE *getnodeattr(int,char *,NODE *,...); (interface.c)
            参数1是需要取得的属性个数,参数2是节点路径,参数3是树指针,后面跟任意个数的属性名字,个数与参数1一致。
    例:root=getnodeattr(1,"/root",tree,"type");
           
    在做好准备后,可以运行xmlread()
    fuction:void xmlread(FILE *,NODE *); (readfile.c)
            根据树的结构,读取xml文档并取相应的值,添加到树中对应节点的result链表上。
            参数1为文件指针,参数2为树指针。


    fuction: void cleanresult(NODE *,int);   (interface.c)
            运行了xmlread()并处理数据后,如果你想用这个树来读取另外一个文档,可以运行它来清除树中结果,以便重新读取。
            参数1为树指针,参数2为0时只将链表result指针置NULL,array_size置0,参数为1时还将释放result链表的内存。               

    ++++++++++
    特性
    ++++++++++

    1. 忽略注释和文档头部声明. <!  >标签当中的内容将被跳过。
    2. 支持<name/>形式的空元素。它们当中没有文本值。
    3. 兼容不严格的格式.
            例如:
            1.像<name  >和<name attr1="   "    attr2=" ">那样多出来的空格也不会影响。       
            2.元素的属性的不用按顺序,把两个要取值的属性调过来写也不影响.
            3.若元素或属性缺失将被跳过,取得的结果个数由node->array_size和node->attr[count]->array_size反映。

    ++++++++++++++++
    注意事项
    ++++++++++++++++
    1.这个库不能用于读html文档。html中有部分元素像<p>等,可以省略结束标志,这不符合xml规范. 在处里文件时读到它们将造成错误.一定要用<name/>这样的形式标记空元素。       
    2.元素的路径类似Xpath,但只能由'/'开头,结尾不能有 '/'.
    3.结果交由用户去处理。如果我来写结果访问的函数可能使程序减低效率,你可以跟据需求选择方便的处理方式。

    4.xml文档声明<?xml ... ?>部份会被跳过。
    [/list:u]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| 发表于 2005-3-5 19:43:39 | 显示全部楼层
以下是测试用的example.c和example.xml, 在vc和gcc中编译通过,我把它也放在了上面的包里.
[code:1]
#include "Cxmlread.h"

void explore_tree(NODE *tree)
{
        int count=0;
do {
        printf("name:%s,needvalue:%d,attrnum:%d\n",\
                tree->name,tree->needvalue,tree->attrnum);
        if(tree->attrnum)
        do
        printf("attr:%d %s\n",count,tree->attr[count]->name);
        while(++count<tree->attrnum);
       
        printf("_______\n");
        if(tree->child)
        {printf("child:%s\n",tree->child->name);explore_tree(tree->child);}
}while(tree=tree->brother);

}

void printresult(struct result *temp)
{
        int count=0;
        while(NULL!=temp)
        {        printf("result %d: %s\n",count++,temp->value);
                temp=temp->next;
        }
}

int main()
{
FILE *fp;
NODE *root,*project,*name,*tree,*path;
tree=xml_init();
fp=fopen("example.xml","r");
   if(!fp){
           printf("file not found!");
           exit(0);
   }

        root=getnodeattr(1,"/root",tree,"type");
        project=getnodeattr(2,"/root/project",tree,"manager","statues");
        name=getnodevalue("/root/project/name",tree);
        path=getnodevalue("/root/project/path",tree);
        getnodeattr(1,"/root/project/path",tree,"host");
       
        explore_tree(tree);
        printf("==============\n\n");

        xmlread(fp,tree);
        fclose(fp);

printf("/root attr[0]: %s\n",root->attr[0]->name);
printresult(root->attr[0]->result);

printf("/root/project attr[0]: %s\n",project->attr[0]->name);
printresult(project->attr[0]->result);

printf("/root/project attr[1]: %s\n",project->attr[1]->name);
printresult(project->attr[1]->result);

printf("/root/project/name\n");
printresult(name->result);

printf("/root/project/path\n");
printresult(path->result);

printf("/root/project/path attr[0]: %s\n",path->attr[0]->name);
printresult(path->attr[0]->result);


cleanresult(tree,1);
//清除结果
}
[/code:1]

example.xml
[code:1]
<?xml version="1.0" encoding="GB2312"?>
<!-- 这是一个不规范、无意义的文档,测试程序的容错能力 -->
<root type="test" encording="zh_CN.GB2312">
        <project  statues="open" manager="M" startime="2004-1-1">
                <name>1</name>
                <type>C</type>
                <path host="No.1">/var/d</path>
        </project>
        <project statues="close" manager="J" startime="2004-2-4">
                <name  >2</name>
                <type>java</type>
                <path >/var/java</path>
        </project>
        <project startime="2004-?-?" manager="k" >
<!--project的属性statues和元素name不存在,会自动跳过。-->
                <type>java</type>
                <path host="local">/var/java1</path>
        </project>
        <project   >
        <name/><!--name没有结束标签,不会读取它的值,其array_size不增加-->
                <type></type>
                <path></path><!--path没有值,返回结果会增加一个长度为0的value字符串-->
        </project>
</root>
[/code:1]

vc的输出:
name:root,needvalue:0,attrnum:1
attr:0 type
_______
child:project
name:project,needvalue:0,attrnum:2
attr:0 manager
attr:1 statues
_______
child:name
name:name,needvalue:1,attrnum:0
_______
name:path,needvalue:1,attrnum:1
attr:0 host
_______
==============

/root attr[0]: type
result 0: test
/root/project attr[0]: manager
result 0: M
result 1: J
result 2: k
/root/project attr[1]: statues
result 0: open
result 1: close
/root/project/name
result 0: 1
result 1: 2
/root/project/path
result 0: /var/d
result 1: /var/java
result 2: /var/java1
result 3:
/root/project/path attr[0]: host
result 0: No.1
result 1: local
Press any key to continue
回复

使用道具 举报

发表于 2005-3-5 22:31:21 | 显示全部楼层
很不错。   
回复

使用道具 举报

发表于 2005-3-7 17:48:36 | 显示全部楼层
太感谢楼主了!
偶自己正打算写XML Library呢,不过既然楼主已经写好了就用楼主的吧
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-6 14:02 , Processed in 0.037504 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表