加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

先弄个XML解析器代码抄一抄 慢慢研究 O(∩_∩)O哈哈~

发布时间:2020-12-16 08:42:17 所属栏目:百科 来源:网络整理
导读:?? 出处:http://bbs.csdn.net/topics/390229172 已经自我放逐好几年了.打算去上班得了.在最后的自由日子里,做点有意义的事吧... 先来下载地址 http://www.kuaipan.cn/file/id_12470514853353274.htm 已经在很多正式,非正式的场合用过了.干脆开源得了.BSD授
??

出处:http://bbs.csdn.net/topics/390229172

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

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

已经在很多正式,非正式的场合用过了.干脆开源得了.BSD授权. 代码比较久远,最后一次修改也在4~5年前了.写的比较BT,只有gcc/vc/icl能编译...不过性能和易用性还是不错的.之前我测试过的,只有几个inplace的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: %dt",node->type );
		switch( node->type ) {
		case xml::_TYPE_TAG:
			printf( "tag name:%sn",xml::tag_iterator(node)->name().c_str() );
			break;
		case xml::_TYPE_COMMENT:
			printf( "comment:%sn",xml::comment_iterator(node)->text().c_str() );
			break;
		case xml::_TYPE_TEXT:
			printf( "text:%sn",xml::text_iterator(node)->text().c_str() );
			break;
		case xml::_TYPE_ATTRIBUTE:
			printf( "attribute:%s=%sn",xml::attribute_iterator(node)->name().c_str(),xml::attribute_iterator(node)->value().c_str() );
			break;
		default:
			printf( "unknown typen" );
			break;
		}
	};

	// 迭代所有子标签
	for( xml::tag_iterator tag = x.root()->begin(); tag != x.root()->end(); ++tag ) {
		// 专用类型的迭代器只能遍历此类型的节点
		printf( "tag:%sn",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不支持,自定义转意也不支持... 用来做配置文件还是不错.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读