XML分析器演示

极光炫影 发表于 2007-03-24 15:02:58

这是一个简易得不能再简易了的XML分析器(其实是替某人完成的作业),
只能用来演示,
好久没写代码了,
不过写起来还是那么快乐
 

/*
            Coded By JGShining
                03/24/2007
*/
 
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
 
#define KEY_OPEN        1
#define KEY_CLOSE       2
#define KEY_FOUND       3
#define KEY_NOT_FOUND   4
#define KEY_ERROR       5
 
struct xml_tree_node
{
    char* name;
    char* value;
    xml_tree_node* next_sibling;
    xml_tree_node* first_child;
   
    xml_tree_node()
    {
        name = NULL;
        value = NULL;
        next_sibling = NULL;
        first_child = NULL;
    }
 
    ~xml_tree_node()
    {
        if(first_child)
            delete first_child;
        if(next_sibling)
            delete next_sibling;
        if(name)
            delete name;
        if(value)
            delete value;
    }
};
 
struct bfs_node
{
    xml_tree_node* tree_node;
    int id;
};
 
void bfs_out(xml_tree_node* root)
{
    if(root == NULL)
        return;
 
    int id = 1;
    bfs_node node, t_node;
    queue<bfs_node> bfs_q;
    xml_tree_node* prev;
 
    node.id = id++;
    node.tree_node = root;
    bfs_q.push(node);
 
    while(!bfs_q.empty())
    {
        node = bfs_q.front();
        bfs_q.pop();
        prev = NULL;
 
        printf("Element %d - %s : ", node.id, node.tree_node->name);
        if(node.tree_node->value)
            printf("%s", node.tree_node->value);
        else
            printf("null");
        printf(", child:");
 
        node.tree_node = node.tree_node->first_child;
        for(; node.tree_node;)
        {
            t_node = node;
            t_node.id = id++;
            bfs_q.push(t_node);
            if(prev)
                putchar(',');
            prev = node.tree_node;
            printf(" Element %d", t_node.id);
            node.tree_node = node.tree_node->next_sibling;
        }
 
        if(prev == NULL)
            printf(" null\n");
        else
            putchar('\n');
    }
}
 
int next_token(FILE* file)
{
    int this_token;
    while(EOF != (this_token = fgetc(file)))
    {
        if(this_token == '<' || this_token == '>')
            break;
    }
    return this_token;
}
 
int next_key(FILE* file, char** buffer, int* type, int* start_pos)
{
    int this_pos, key_length, token;
    if('<' == (token = next_token(file)))
    {
        *start_pos = ftell(file) - 1;
        token = fgetc(file);
        if(token == '/')
            *type = KEY_CLOSE;
        else
        {
            *type = KEY_OPEN;
            ungetc(token, file);
        }
        this_pos = ftell(file);
        if('>' == (token = next_token(file)))
        {
            key_length = ftell(file) - this_pos - 1;
            if(key_length == 0)
                *buffer = NULL;
            else
            {
                *buffer = new char[key_length + 1];
                this_pos = ftell(file);
                fseek(file, this_pos - key_length - 1, SEEK_SET);
                fread(*buffer, key_length, 1, file);
                (*buffer)[key_length] = 0;
                fseek(file, this_pos, SEEK_SET);
            }
        }
        else
            return KEY_ERROR;
    }
    else if(token == EOF)
        return KEY_NOT_FOUND;
    else
        return KEY_ERROR;
    return KEY_FOUND;
}
 
void read_value(FILE* file, char** buffer, int start_pos, int end_pos)
{
    if(end_pos <= start_pos)
    {
        *buffer = NULL;
        return;
    }
    int this_pos = ftell(file);
    fseek(file, start_pos, SEEK_SET);
    *buffer = new char[end_pos - start_pos + 1];
    fread(*buffer, end_pos - start_pos, 1, file);
    (*buffer)[end_pos - start_pos] = 0;
    fseek(file, this_pos, SEEK_SET);
}
 
bool parse(FILE* file, xml_tree_node* parent, int start_pos)
{
    xml_tree_node* node = NULL, *prev_child = NULL;
    char* key_name;
    int type, next_pos, res;
 
    while(KEY_FOUND == (res = next_key(file, &key_name, &type, &next_pos)))
    {
        if(type == KEY_CLOSE && strcmp(key_name, parent->name) == 0)
        {
            if(parent->first_child == NULL)
                read_value(file, &(parent->value), start_pos, next_pos);
            return true;
        }
        else if(type == KEY_OPEN)
        {
            node = new xml_tree_node;
            node->name = key_name;
            if(prev_child == NULL)
                parent->first_child = node;
            else
                prev_child->next_sibling = node;
            prev_child = node;
            if(!parse(file, node, ftell(file)))
                return false;
        }
        else
            return false;
    }
 
    return false;
}
  
int main(int argc, char** argv)
{
    xml_tree_node* root;
    FILE* file;
    char* key_name;
    int type, start_pos, res;
    freopen("parse_result.txt", "w", stdout);
    if(argc < 2)
    {
        printf("not enough parameters\n");
        return 0;
    }
 
    if(file = fopen(argv[1], "rb"))
    {
        res = next_key(file, &key_name, &type, &start_pos);
        if(res == KEY_FOUND && type == KEY_OPEN)
        {
            root = new xml_tree_node;
            root->name = key_name;
            if(parse(file, root, ftell(file)))
                bfs_out(root);
            else
                printf("file format error\n");
            delete root;
        }
        else if(res == KEY_ERROR)
            printf("file format error\n");
        fclose(file);
    }
    else
        printf("failed to open XML file\n");
 
    return 0;
}
关键词(Tag): xml parser

曾经的这一天...


收藏: QQ书签 del.icio.us 订阅: Google 抓虾

最新评论

发表评论

* 昵称

已经注册过? 请登录

新用户请先注册 以便能显示头像及追踪评论回复

Email
网址
* 评论
表情
 
 

分类小组论坛
杂谈, 娱乐、八卦, 文学、艺术, 体育, 旅游、同城, 象牙塔, 情感, 时尚、生活, 星座, 科技

请注意遵守中华人民共和国法律法规, 如威胁到本站生存, 将依法向有关部门报告, 同时本站的相关记录可能成为对您不利的证据.

相关法律法规
全国人大常委会关于维护互联网安全的决定
中华人民共和国计算机信息系统安全保护条例
中华人民共和国计算机信息网络国际联网管理暂行规定
计算机信息网络国际联网安全保护管理办法
计算机信息系统国际联网保密管理规定