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. 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 {
18
public:
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
}