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事件。