gloox代码分析2 - xml parser模块
gloox自己实现了xml的解析模块,没有用到第三方的库(tinyXML,expat )主要涉及的文件:
tag.h (tag.cpp)
taghandler.h
parser.h (parser.cpp)
1. Tag一个Tag就是一个XML元素
例如:
a.
<book kind='computer'>
<store id='23'/>
<author>
qiang
</author>
</book>
b. <book id='32'/>
c. <book>name1</book>
首先介绍一个概念: escape-string,何为escape-string?
在escape-string中:
'&'转换成&, '<'转换成<, '>'转换成>.
编码表如下:
//////////////////////////////////////////////////////////////////////////
// 编码表 (中间的空格去掉,这里只是为了方便显示):
// -------------------------------------------------------
// | 字符 | 十进制 | 十六进制 | THML字符集 | Unicode |
// -------------------------------------------------------
// | " 双引号 | & # 34; | & # x22; | " | \u0022 |
// -------------------------------------------------------
// | ' 单引号 | & # 39; | & # x27; | & apos; | \u0027 |
// -------------------------------------------------------
// | & 与 | & # 38; | & # x26; | & amp; | \u0026 |
// -------------------------------------------------------
// | < 小于号 | & # 60; | & # x3C; | & lt; | \u003c |
// -------------------------------------------------------
// | > 大于好 | & # 62; | & # x3E; | & gt; | \u003e |
// -------------------------------------------------------
gloox - APIs
Tag::escape() 功能: string -> escape-string
Tag::relax() 功能: escape-string -> string
主要成员变量:
attributes - 所有属性的list
name - 节点名字
cdata - 节点数据,例如<name>cdata</name>中的cdata
children - 所有的子节点
parent - 父节点指针,如果没有则为空
bool incoming - 表示构造xml node的时候传入的字符串是否是escape-string,如果是,需要在构造的时候调用relex把escape-string转换成string.
主要方法:
也就是一些针对name\children\attributes\cdata进行增加\删除\修改的方法
xml()方法返回该节点的一个完整的xml数据流
findTag和findTagList提供对XPath的支持.
例如:
屏幕将输出:
<book kind='computer'><store id='23'/><author>qiang</author></book>
1
#include
<
iostream
>
2 #include " tag.h "
3
4 #pragma comment( lib, " gloox.lib " )
5 using namespace gloox;
6
7 // <book kind='computer'>
8 // <store id='23'/>
9 // <author>
10 // qiang
11 // </author>
12 // </book>
13 //
14
15
16 int main( int argc, char * argv[] ) {
17 Tag* tag_book = new Tag( "book");
18 tag_book->addAttribute( "kind", "computer" );
19
20 Tag* tag_store = new Tag( "store" );
21 tag_store->addAttribute( "id", "32" );
22
23 Tag* tag_author = new Tag( "author", "qiang" );
24
25 tag_book->addChild( tag_store );
26 tag_book->addChild( tag_author );
27
28 std::cout<<tag_book->xml()<<std::endl;
29 return 0;
30}
2 #include " tag.h "
3
4 #pragma comment( lib, " gloox.lib " )
5 using namespace gloox;
6
7 // <book kind='computer'>
8 // <store id='23'/>
9 // <author>
10 // qiang
11 // </author>
12 // </book>
13 //
14
15
16 int main( int argc, char * argv[] ) {
17 Tag* tag_book = new Tag( "book");
18 tag_book->addAttribute( "kind", "computer" );
19
20 Tag* tag_store = new Tag( "store" );
21 tag_store->addAttribute( "id", "32" );
22
23 Tag* tag_author = new Tag( "author", "qiang" );
24
25 tag_book->addChild( tag_store );
26 tag_book->addChild( tag_author );
27
28 std::cout<<tag_book->xml()<<std::endl;
29 return 0;
30}
2. TagHandler是一个接收parser解析完成的tag的接口,继承该类,则可以接收parser解析的tag对象事件.
只有一个接口
virtual void handleTag( Tag *tag ) = 0 - 接收解析完的tag
3. Parser一个XML解析器
提供的接口非常简洁,只需要一个TagHandler来构造,该handler接收并处理解析的tag,另外只有一个feed接口来填充数据.
要注意的是feed接口填充的数据必须是一个格式正确的xml,否则无法解析,也就是说parser不会判断xml的格式。
例如:
下面的例子中对feed来说分开填充和一次性填充数据的效果是一样的,也就是scenario1和scenario2的效果是一样的,这也刚好和上层应用中TCP 流处理的方式统一,对于接收到服务器端的XML流,无论是否完整,只需要直接feed就可以了。handlerTag方法将收到两个
xml tag解析完成的事件,分别来自scenario1和scenario2,屏幕将输出:
<book kind='computer'><store id='23'/><author>qiang</author></book>
<book kind='computer'><store id='23'/><author>qiang</author></book>
1
#include
<
iostream
>
2 #include " tag.h "
3 #include " parser.h "
4
5 #pragma comment( lib, " gloox.lib " )
6 using namespace gloox;
7
8 // <book kind='computer'>
9 // <store id='23'/>
10 // <author>
11 // qiang
12 // </author>
13 // </book>
14 //
15 //
16
17 class TagHandlerImpl : public TagHandler {
18public:
19 ~TagHandlerImpl() {}
20
21 void run() {
22 Parser* parser = new Parser(this);
23 // scenario1
24 std::string data = "<book kind='computer'><store id='23'/><author>qiang</author></book>";
25 parser->feed( data );
26
27 // scenario2
28 std::string data1 = "<book kind='computer";
29 std::string data2 = "'><store id='23'/><auth";
30 std::string data3 = "or>qiang</author></book>";
31 parser->feed( data1 );
32 parser->feed( data2 );
33 parser->feed( data3 );
34 }
35
36 void handleTag( Tag *tag ) {
37 std::cout<<tag->xml()<<std::endl;
38 }
39} ;
40
41 int main( int argc, char * argv[] ) {
42 TagHandlerImpl* taghandlerImpl = new TagHandlerImpl();
43 taghandlerImpl->run();
44
45 return 0;
46}
2 #include " tag.h "
3 #include " parser.h "
4
5 #pragma comment( lib, " gloox.lib " )
6 using namespace gloox;
7
8 // <book kind='computer'>
9 // <store id='23'/>
10 // <author>
11 // qiang
12 // </author>
13 // </book>
14 //
15 //
16
17 class TagHandlerImpl : public TagHandler {
18public:
19 ~TagHandlerImpl() {}
20
21 void run() {
22 Parser* parser = new Parser(this);
23 // scenario1
24 std::string data = "<book kind='computer'><store id='23'/><author>qiang</author></book>";
25 parser->feed( data );
26
27 // scenario2
28 std::string data1 = "<book kind='computer";
29 std::string data2 = "'><store id='23'/><auth";
30 std::string data3 = "or>qiang</author></book>";
31 parser->feed( data1 );
32 parser->feed( data2 );
33 parser->feed( data3 );
34 }
35
36 void handleTag( Tag *tag ) {
37 std::cout<<tag->xml()<<std::endl;
38 }
39} ;
40
41 int main( int argc, char * argv[] ) {
42 TagHandlerImpl* taghandlerImpl = new TagHandlerImpl();
43 taghandlerImpl->run();
44
45 return 0;
46}