a、解析过程中遇到</字符,进入endTag解析。
b、代码详解
public int parseEndTag() throws XmlPullParserException, IOException {
//ASSUMPTION ch is past "</"
// [42] ETag ::= '</' Name S? '>'
//紧接在</后面的字符需要检查是否符合isNameStartChar()条件
char ch = more();
if(!isNameStartChar(ch)) {
throw new XmlPullParserException(
"expected name start and not "+printable(ch), this, null);
}
//类似parseStartTag,将posStart置于<字符
posStart = pos - 3;
final int nameStart = pos - 1 + bufAbsoluteStart;
do {
ch = more();
} while(isNameChar(ch));
// now we go one level down -- do checks
//--depth; //FIXME
// check that end tag name is the same as start tag
//String name = new String(buf, nameStart - bufAbsoluteStart,
// (pos - 1) - (nameStart - bufAbsoluteStart));
//int last = pos - 1;
int off = nameStart - bufAbsoluteStart;
//final int len = last - off;
final int len = (pos - 1) - off;
final char[] cbuf = elRawName[depth];
//如果与startTag的元素名称长度不一致,抛异常
if(elRawNameEnd[depth] != len) {
// construct strings for exception
final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
final String endname = new String(buf, off, len);
throw new XmlPullParserException(
"end tag name </"+endname+"> must match start tag name <"+startname+">"
+" from line "+elRawNameLine[depth], this, null);
}
//如果与startTag的元素名称不完全相同,抛异常
for (int i = 0; i < len; i++)
{
if(buf[off++] != cbuf[i]) {
// construct strings for exception
final String startname = new String(cbuf, 0, len);
final String endname = new String(buf, off - i - 1, len);
throw new XmlPullParserException(
"end tag name </"+endname+"> must be the same as start tag <"+startname+">"
+" from line "+elRawNameLine[depth], this, null);
}
}
//忽略元素名称结尾部分空字符
while(isS(ch)) { ch = more(); } // skip additional white spaces
//没有>紧随则抛出异常
if(ch != '>') {
throw new XmlPullParserException(
"expected > to finish end tag not "+printable(ch)
+" from line "+elRawNameLine[depth], this, null);
}
//namespaceEnd = elNamespaceCount[ depth ]; //FIXME
posEnd = pos;
pastEndTag = true;
return eventType = END_TAG;
}
c、代码要点
c.1、第一个字符必须符合isNameStartChar()条件。xml规范中大多有这个要求,名称后面出现空格等空白字符是允许的。
c.2、解析元素名称,检查与startTag对应元素名称是否一致。
c.3、紧接元素名称后,是否有>字符收尾。
c.4、返回END_TAG事件。