出處:http://bbs.csdn.net/topics/390229172
??????? 已經自我放逐好幾年了.打算去上班得了.在最后的自由日子里,做點有意義的事吧...
先來下載地址??? 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不支持,自定義轉意也不支持...
用來做配置文件還是不錯.