XMPP协议的JAVA实现,采用XMLPULL协议是比较好的实现策略,下了源码,记录下,不定时更新。
一、核心处理流程:
1、pc策略(pc是MXParser类中定义的一个字符数组char[],个人理解翻译为Processed Character处理过的字符)
MXParser实现中通过Reader读到的字符会全部原封不动存储在buf这个字符数组中。在某次next()逻辑中,比如某tag中的文本数据解析过程中,存在CDATA数据或Reference数据时,需要将解析后的字符存储到pc这个字符数组中,如果这种数据在本次next()解析过程中出现多次,即在处理新的CDATA数据或Reference数据时,发现hadCharData为true,需要进行joinPC合并,并将needMerging置为false。pc在每次next()的起始处是被从头覆写的,pcStart和pcEnd会归0.
2、nextToken()
a、进行xml头解析parseProlog()
包括BOM、<?xml version='1.0' encoding='UTF-8' standalone='yes'?>和根元素的解析
b、循环进行根元素中的元素分析
b.1、遇到"<"字符,发现已经有字符数据,退出,返回TEXT事件;没有字符数据,则more()下一个字符进行分支判定,分支包括/(是否标签结尾)、!(是否注释!-或CDATA![)、?(PI解析,存在疑问)、合法元素起始字符(正常走parseStartTag()且return该方法返回事件,存在疑问)、其它字符抛异常。
b.1.1、/(是否标签结尾)
b.2、遇到"&"字符,发现已经有字符数据,退出,返回TEXT事件;没有字符数据,则进行reference解析
3、next()
与nextToken()流程基本相同,只是遇到特定字符时,不会中断返回附加事件,流程更简单,这也是只用讲解nextToken()实现逻辑的原因。
XmlPullParser里共定义了5类核心事件,即next()和nextToken()都会关注的事件:
int START_DOCUMENT = 0;
int END_DOCUMENT = 1;
int START_TAG = 2;
int END_TAG = 3;
int TEXT = 4;
6类附加事件,即仅nextToken()会关注的事件。
int CDSECT = 5;
int ENTITY_REF = 6;
int IGNORABLE_WHITESPACE = 7;
int PROCESSING_INSTRUCTION = 8;
int COMMENT = 9;
int DOCDECL = 10;
4、buf维护策略
a、每次通过Reader最多读取的内容块大小为READ_CHUNK_SIZE 8K。
b、JVM剩余内存超1000000,则buf定义为char[READ_CHUNK_SIZE],否则为char[256]。
c、设定了95%的容量使用限制,当buf填充超过这个限制,要进行压缩或扩容处理。
压缩就是把未处理的buf部分直接从buf0位进行覆盖;扩容就是直接两倍buf长度,并把未处理的buf部分直接从buf0位进行覆盖。
选择压缩还是扩容,取决于下面的因素:
*如果是xml声明部分处理过程中,禁止压缩(理由没想通)
*如果待分析的buf内容全部在超出限制部分,则适宜于压缩
*如果待分析的buf内容起始位置尚未达到buf的一半,且小于限制,则适宜于扩张
d、超出使用限制,进行扩容或压缩后,很多变量需要重新设值。
*bufStart归0,因为待解析buf内容现在都是从0开始。
*bufEnd也要随bufStart缩减bufStart长度值。
*pos也要随bufStart缩减bufStart长度值。
*posStart、posEnd同上。
*bufAbsoluteStart要准确记录这次缩减,从0调整为bufStart。后续如果再次调整,要再加bufStart。