在上篇文章中,简单介绍了sax解析xml的一种方式,它是继承defaulthandler方式,并重写其中的几个方法来实现的。
接下来说的第二种方式是用rootelement这个类来解析的,rootelement 内置了defaulthandler的子类,
rootelement 源码如下:
public class rootelement extends element {
final handler handler = new handler();
/**
* constructs a new root element with the given name.
*
* @param uri the namespace
* @param localname the local name
*/
public rootelement(string uri, string localname) {
super(null, uri, localname, 0);
}
/**
* constructs a new root element with the given name. uses an empty string
* as the namespace.
*
* @param localname the local name
*/
public rootelement(string localname) {
this("", localname);
}
/**
* gets the sax {@code contenthandler}. pass this to your sax parser.
*/
public contenthandler getcontenthandler() {
return this.handler;
}
class handler extends defaulthandler {
locator locator;
int depth = -1;
element current = null;
stringbuilder bodybuilder = null;
@override
public void setdocumentlocator(locator locator) {
this.locator = locator;
}
@override
public void startelement(string uri, string localname, string qname,
attributes attributes) throws saxexception {
int depth = ++this.depth;
if (depth == 0) {
// this is the root element.
startroot(uri, localname, attributes);
return;
}
// prohibit mixed text and elements.
if (bodybuilder != null) {
throw new badxmlexception("encountered mixed content"
+ " within text element named " + current + ".",
locator);
}
// if we're one level below the current element.
if (depth == current.depth + 1) {
// look for a child to push onto the stack.
children children = current.children;
if (children != null) {
element child = children.get(uri, localname);
if (child != null) {
start(child, attributes);
}
}
}
}
void startroot(string uri, string localname, attributes attributes)
throws saxexception {
element root = rootelement.this;
if (root.uri.compareto(uri) != 0
|| root.localname.compareto(localname) != 0) {
throw new badxmlexception("root element name does"
+ " not match. expected: " + root + ", got: "
+ element.tostring(uri, localname), locator);
}
start(root, attributes);
}
void start(element e, attributes attributes) {
// push element onto the stack.
this.current = e;
if (e.startelementlistener != null) {
e.startelementlistener.start(attributes);
}
if (e.endtextelementlistener != null) {
this.bodybuilder = new stringbuilder();
}
e.resetrequiredchildren();
e.visited = true;
}
@override
public void characters(char[] buffer, int start, int length)
throws saxexception {
if (bodybuilder != null) {
bodybuilder.append(buffer, start, length);
}
}
@override
public void endelement(string uri, string localname, string qname)
throws saxexception {
element current = this.current;
// if we've ended the current element...
if (depth == current.depth) {
current.checkrequiredchildren(locator);
// invoke end element listener.
if (current.endelementlistener != null) {
current.endelementlistener.end();
}
// invoke end text element listener.
if (bodybuilder != null) {
string body = bodybuilder.tostring();
bodybuilder = null;
// we can assume that this listener is present.
current.endtextelementlistener.end(body);
}
// pop element off the stack.
this.current = current.parent;
}
depth--;
}
}
}
以上是rootelement类得源码,从源码可以看出,它只是将defaulthandler简单的处理一下。
具体应用可以参照我写的测试源码
/**
* sax解析xml的第二种方式
* 用xmlreader 也是sax的一种方式
* @return
*/
private string saxparsesecond(){
//读取src下xml文件
inputstream inputstream =
this.getclass().getclassloader().getresourceasstream("saxtest.xml");
saxparserfactory factory = saxparserfactory.newinstance();
try {
saxparser parse = factory.newsaxparser();
xmlreader reader = parse.getxmlreader();
reader.setcontenthandler(getrootelement().getcontenthandler());
reader.parse(new inputsource(inputstream));
} catch (parserconfigurationexception e) {
e.printstacktrace();
} catch (saxexception e) {
e.printstacktrace();
} catch (ioexception e) {
e.printstacktrace();
}
return result;
}
/**
*
* @return 返回设置好处理机制的rootelement
*/
private rootelement getrootelement(){
/*rootelement代表着根节点,参数为根节点的tagname*/
rootelement rootelement = new rootelement("classes");
/*获取一类子节点,并为其设置相应的事件
* 这里需要注意,虽然我们只设置了一次group的事件,但是我们文档中根节点下的所有
* group却都可以触发这个事件。
* */
element groupelement = rootelement.getchild("group");
// 读到元素开始位置时触发,如读到<group>时
groupelement.setstartelementlistener(new startelementlistener() {
@override
public void start(attributes attributes) {
// log.i("test", "start");
string groupname = attributes.getvalue("name");
string groupnum = attributes.getvalue("num");
result = result+"groupname ="+groupname+"groupnum = "+groupnum+"\n";
}
});
//读到元素结束位置时触发,如读到</group>时
groupelement.setendelementlistener(new endelementlistener() {
@override
public void end() {
}
});
element personelement = groupelement.getchild("person");
//读取<person>标签触发
personelement.setstartelementlistener(new startelementlistener() {
@override
public void start(attributes attributes) {
string personname = attributes.getvalue("name");
string age = attributes.getvalue("age");
result = result+"personname ="+personname+"age = "+age+"\n";
}
});
//读取</person>标签触发
personelement.setendelementlistener(new endelementlistener() {
@override
public void end() {
}
});
element chinese = personelement.getchild("chinese");
// chinese.settextelementlistener(new textelementlistener() {
//
// @override
// public void end(string body) {
// // todo auto-generated method stub
//
// }
//
// @override
// public void start(attributes attributes) {
// // todo auto-generated method stub
//
// }
// });
// 读到文本的末尾时触发,这里的body即为文本的内容部分
chinese.setendtextelementlistener(new endtextelementlistener() {
@override
public void end(string body) {
pattern p = pattern.compile("\\s*|\t|\r|\n");
matcher m = p.matcher(body);
body = m.replaceall("");
result = result+"chinese ="+body;
}
});
element english = personelement.getchild("english");
english.setendtextelementlistener(new endtextelementlistener() {
@override
public void end(string body) {
pattern p = pattern.compile("\\s*|\t|\r|\n");
matcher m = p.matcher(body);
body = m.replaceall("");
result = result+"english ="+body+"\n";
}
});
return rootelement;
}
我们都知道通过saxparser对象解析xml的方式,这里我们又从代码中看到了利用另一个对象xmlreader进行解析,那么两者到底有什么联系和区别呢?
其实saxparser是在sax 1.0 定义的,而xmlreader则是在2.0中才开始出现的。你可以认为xmlreader的出现是为了替代saxparser解析的,两者本质上干的事情是一样的,只不过xmlreader的功能更加的强悍而已。
关于xmlreader的获取方式,除了通过saxparser的getxmlreader方法获得之外,我们还可以通过以下两种方式。
xmlreader parser=xmlreaderfactory.createxmlreader(); (1)
xmlreader parser=xmlreaderfactory.createxmlreader(string classname); (2)
以上就是android sax解析xml文件(二)的内容。
