zoukankan      html  css  js  c++  java
  • 自己写的简单xml解析器

    已经自我放逐好几年了.打算去上班得了.在最后的自由日子里,做点有意义的事吧...

    先来下载地址
    http://www.kuaipan.cn/file/id_12470514853353274.htm

    已经在很多正式,非正式的场合用过了.干脆开源得了.BSD授权.
    代码比较久远,最后一次修改也在4~5年前了.写的比较BT,只有gcc/vc/icl能编译...
    不过性能和易用性还是不错的.之前我测试过的,只有几个in place的xml解析器稍微比我的快一点点.
    下面是示例代码:

    C/C++ code?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    // xml-test.cpp
    #include <stdio.h>
    #include "xml.h"
     
    // 自定义FILE*输出策略
    class cfile_writer {
        FILE *_fp;
        cfile_writer &operator = ( const cfile_writer& );
        cfile_writer( const cfile_writer& );
    public:
        cfile_writer( FILE *fp ) : _fp(fp) {
            fputs"-----------------\n", _fp );
        }
        ~cfile_writer() {
            fputs"\n", _fp );
        }
        // 策略不用预分配空间
        // 如果为1, 在输出前会计算要占空间大小, 并调用resize接口进行预分配.
        static const int need_pre_allocate = 0;
        // 预分配接口
        bool resize( size_t size ) const return true; }
        // 输出一个字符
        void write( char value ) const  {
            fputc( value, _fp );
        }
        // 输出一个字符串, 长度由size指定
        void write( const char *value, size_t size ) const  {
            fwrite( value, 1, size, _fp );
        }
    };
     
    int main() {
        using namespace cpp::utils;
        const char xml_string[] = "<root attr=\"root attr\"><node prop=\"234\"/>text content<!-- comment --></root>";
        xml x;
     
        // 解析xml_string, 用不同的reader策略可以从不同的源中读数据
        // 也可以自定义读策略, 以适应不同的需求
        // 解析成功返回true.如果只有部分解析成功时虽然返回false,但已经解析成功的内容仍然可用
        // 如果宏XML_WITH_PARSE_STATUS设置为1(默认为0).可以从x.info()中得到解析器停止的位置,方便调试.但会降低解析器性能.
        x.parse( xml_reader( xml_string ) );
     
        xml x2;
        x2.push_back( xml::tag("root-x2") );    // 直接向空xml对象中添加标签
        x2("root-x2").push_back( xml::text("text value") );
        x2.write( cfile_writer( stderr ) );
         
        // 输出/root/node[prop]的值
        // ()运算符为标签查找,返回指定名称的第一个标签.[]运算符为属性查找,返回指定名称的属性.
        printf"/root/node[prop] = [%s]\n", x("root")("node")["prop"].value().c_str() );
        // 这里使用了null object模式,所以无需检查每一步的返回结果,不会因为访问非法节点而产生异常.简化使用
        printf"null object test:[%s]\n", x("roxxot")("noeede")["prop"].value().c_str() );
     
        // 把root标签转成其迭代器(&运算符)
        xml::tag_iterator root_tag = &x("root");
         
        // 迭代所有子节点
        for( xml::node_iterator node = x.root()->begin(); node != x.root()->end(); ++node ) {
            // xml::node_iterator为通用节点迭代器, 可以指向任何类型的节点.
            // 并可以转型成任意的其它迭代器. 但如果指向的节点类型和目标迭代器类型不符, 则会自动指向下一个合法的节点
            // 比如: <abc/><!--comment-->
            //       这里有两个节点,一个abc标签,一个注释.
            //       如果有当前node迭代器指向abc标签.
            //            把node转成xml::tag_iterator类型时,则指向的节点不变.
            //            如果转成xml::comment_iterator时则会指向后面的注释.
            //            如果转成其它不存在类型的节点,则会指向容器的末尾.
            printf"node type: %d\t", node->type );
            switch( node->type ) {
            case xml::_TYPE_TAG:
                printf"tag name:%s\n", xml::tag_iterator(node)->name().c_str() );
                break;
            case xml::_TYPE_COMMENT:
                printf"comment:%s\n", xml::comment_iterator(node)->text().c_str() );
                break;
            case xml::_TYPE_TEXT:
                printf"text:%s\n", xml::text_iterator(node)->text().c_str() );
                break;
            case xml::_TYPE_ATTRIBUTE:
                printf"attribute:%s=%s\n", xml::attribute_iterator(node)->name().c_str(), xml::attribute_iterator(node)->value().c_str() );
                break;
            default:
                printf"unknown type\n" );
                break;
            }
        };
     
        // 迭代所有子标签
        for( xml::tag_iterator tag = x.root()->begin(); tag != x.root()->end(); ++tag ) {
            // 专用类型的迭代器只能遍历此类型的节点
            printf"tag:%s\n", tag->name().c_str() );
        }
     
        // 在/root/node下添加abc标签, 并保存指向标签的迭代器
        xml::tag_iterator abc_tag = x("root")("node").push_back( xml::tag( "abc" ) );
        // 用abc_tag迭代器向abc标签添加属性
        abc_tag->push_back( xml::attribute( "tag-prop""value abcdefg" ) );
        // 在abc标签前插入注释
        abc_tag->parent().insert( abc_tag, xml::comment( "tag-prop comment" ) );
        // 把xml_string解析出来,并将结果放到abc_tag所指向的标签里
        abc_tag->parse( xml_reader( xml_string ) );
        // 深拷贝x2对象中的根节点到abc标签中,实现跨xml对象进行节点复制
        abc_tag->push_front_copy( x2.root() );
        // 输出abc_tag指向的标签, 第二个参数true表示只输出内容标签的内容,不包含标签本身及属性
        abc_tag->write( cfile_writer( stdout ), true );
        // 删除第一个子节点
        abc_tag->erase( abc_tag->begin() );
        abc_tag->write( cfile_writer( stdout ), true );
        // 不能直接删除孙节点
        x.erase( xml::tag_iterator(abc_tag->begin()) );    // 转型成xml::tag_iterator是因为abc的第一个节点是属性.删除不直观.用标记会明显点
        abc_tag->write( cfile_writer( stdout ) );    // 没有删掉
        // 递归删除可以成功
        x.recursion_erase( xml::tag_iterator(abc_tag->begin()) );
        abc_tag->write( cfile_writer( stdout ) );    // 已经删除成功
        return 0;
    }

    只支持基本语法,很多东西不支持.比如:CDATA不支持,自定义转意也不支持...
    用来做配置文件还是不错.

    原文地址

    作者:Work Hard Work Smart
    出处:http://www.cnblogs.com/linlf03/
    欢迎任何形式的转载,未经作者同意,请保留此段声明!

  • 相关阅读:
    第一节 软件测试概述(2)
    第一节 软件测试概述(1)
    Sql语句,查询效率
    Js cdn 学习
    Java内部类详解
    UML用例图
    UML类图几种关系的总结
    JFinal框架_定时触发程序
    利用EXCEL函数LINEST进行统计学中的回归分析
    Windows 10 64 Bit 编译安装 PyLucene 8.3.0
  • 原文地址:https://www.cnblogs.com/linlf03/p/2843273.html
Copyright © 2011-2022 走看看