开源个我自己写的简单xml解析器~~~~

redleaves 2012-09-28 02:21:58
加精
已经自我放逐好几年了.打算去上班得了.在最后的自由日子里,做点有意义的事吧...

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

已经在很多正式,非正式的场合用过了.干脆开源得了.BSD授权.
代码比较久远,最后一次修改也在4~5年前了.写的比较BT,只有gcc/vc/icl能编译...
不过性能和易用性还是不错的.之前我测试过的,只有几个in place的xml解析器稍微比我的快一点点.
下面是示例代码:
// 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不支持,自定义转意也不支持...
用来做配置文件还是不错.
...全文
8156 132 打赏 收藏 转发到动态 举报
写回复
用AI写文章
132 条回复
切换为时间正序
请发表友善的回复…
发表回复
娜乌西卡_ 2015-03-14
  • 打赏
  • 举报
回复
引用 1 楼 redleaves 的回复:
自己先顶~~~ 另外: 其中有vs调试器的可视化脚本.用vs的同志可以在调试时直接看到xml的结构和内容. 用法自己上网找..关键字:autoexp.dat
楼主,代码无法看到,可否再传一份。
yazinihao 2014-12-11
  • 打赏
  • 举报
回复
快盘维护中,支持楼主,顺求源码
zm0011 2013-12-13
  • 打赏
  • 举报
回复
楼主的超级NOTEPAD能开源么,很感兴趣呢
mLee79 2013-11-15
  • 打赏
  • 举报
回复
引用 39 楼 redleaves 的回复:
[Quote=引用 36 楼 的回复:]不错, 不过还是跟喜欢自动生成代码的, 曾经打算写一个解析类似描述, 自动生成C代码的工具, 后来只写了个半成品, 然后就很少用到xml了, 结果就没完成. document [ name("root") , property { [option , defval( NULL ) , name("sprop")] String sPropRoot; ……[/Quote]YACC之流在算法上的确是可以做到相当的优化了.但问题是它的实现的确不怎么优化.手写解析器超越它比较容易.以前玩这个的时候,还用它实现过一个脚本. 自动生成代码.生成的好了还好,生成的比较烂的话,维护可是个麻烦....甚至一度我宁愿手工做状态机,写状态表. 最近做个东西,用了GSOAP...直接生成几个20M的源文件.搞的LD都要报符号太多... 如果你的代码生成器能做到输入需求,输出应用程序....那就完美了^_^
SAX解析xml本身用正规文法配一个简单的堆栈就可以, 如果时间充分我会使用DFA做, 我相信手写的解析器几乎无法超越, 用yacc是为了根据DTD提取信息 . 好多年没有遇到要用xml的时候了, 以后遇到了就去把这个代码生成器写完 . 一般我生成的代码导出的符号会很少, 基本上就几个常量数组加上一个函数即可, 嘻嘻.
sunyang500 2013-11-14
  • 打赏
  • 举报
回复
楼主下不了啊。地址无效。。。。
sunyang500 2013-11-14
  • 打赏
  • 举报
回复
路过顶一下,被COM解XML毒害过的路过下。
searching999 2013-01-29
  • 打赏
  • 举报
回复
顶一个,感谢分享
暮色已沉 2012-12-04
  • 打赏
  • 举报
回复
mark .
ctreewang 2012-12-03
  • 打赏
  • 举报
回复
引用 26 楼 clever101 的回复:
楼主,效率如何啊!贴张常用开源xml库的效率比较图吧:
经常用的tinyxml效率这么差?
breakfisher 2012-12-03
  • 打赏
  • 举报
回复
支持,学习了
_程序员 2012-12-03
  • 打赏
  • 举报
回复
62708807 职业C/C++交流群 以前很火的,后来被群主清空了 现在找人
Ahh_Freshmeat 2012-12-03
  • 打赏
  • 举报
回复
支持奉献支持奉献
clever101 2012-12-03
  • 打赏
  • 举报
回复
引用 120 楼 wallwind 的回复:
引用 26 楼 clever101 的回复:楼主,效率如何啊!贴张常用开源xml库的效率比较图吧: 经常用的tinyxml效率这么差?
tinyxml的效率本来就不怎样,名气大罢了。
userisexists 2012-10-13
  • 打赏
  • 举报
回复
我也写了个简单的,然后更简单:
xml = xml.create;
xml.load("c:\a.xml");

string value;
// search
if (xml.find("root\settings\tag1', value))
printf("value: %s", value);
else
printf("find error");

// search attr
if (xml.findattr("root\settings\tag1', "attrname", value))
printf("attr value: %s", value);
else
printf("find error");

// delete
if (xml.delete("root\settings\tag1"))
printf("delete ok");
else
printf("delete error");

// modify or add
value = "value test";
if (xml.modify("root\settings\tagXXX", value))
printf("modify ok");
else
printf("modify error");

// save
xml.save("c:\xxx.xml");

就是全部功能,嘿
thuo7120253 2012-10-10
  • 打赏
  • 举报
回复
懂得分享,懂得爱
  • 打赏
  • 举报
回复
c 收藏
LAONINGA098 2012-10-10
  • 打赏
  • 举报
回复
感谢分享
Hayasaky 2012-10-09
  • 打赏
  • 举报
回复
还不错啊,来帮顶了!!!
__________________ 2012-10-08
  • 打赏
  • 举报
回复
不错,支持。
zumimi 2012-10-08
  • 打赏
  • 举报
回复
绝对支持原创,非常好!!
加载更多回复(100)

65,131

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧