Pull解析
使用HttpGet从服务器获得xml的文件
然后调用parseXMLWithPull(response);
parseXMLWithPull类
private void parseXMLWithPull(String xmlData){
try{
XmlPullParserFactory factory=XmlPullParseFactory.newInstance();
XmlPullParse xmlPullParser = factory.newPullParse();
xmlPullParser.setInput(new StringReader(xmlData));
int eventType = xmlPullParser.getEventType();
String id="";
String name ="";
String version="";
while(eventType!=XmlPullParser.END_DOCUMENT){
String nodeName = xmlPullParser.getName();
switch(eventType){
case XmlPullParser.START_TAG:{
if("id".equals(nodeName)){
id=xmlPullParser.nextText();
}else if("name".equals(nodeName)){
name=xmlPullParser.nextText();
}else if ("version".equals(nodeName)){
version=xmlPullParser.nextText();
}
break;
}
//完成解析某个节点
case XmlPullParser.END_TAG:{
if("app".equals(nodeName)){
Log.d("aaa","id is"+id);
Log.d("aaa","name is"+name);
Log.d("aaa","version is"+version);
}
break;
}
default:
break;
}
eventType=xmlPullParse.next();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
- 这里首先要获得一个XmlPullParserFactory的实例,并借助这个实例得到XmlPullParser对象,然后调用XmlPullParser的setInput()方法将服务器返回的xml数据设置进去就可以解析了。
- 解析过程,通过getEventType()可以得到当前的解析时间,然后在一个while循环里进行解析,如果当前的解析事件不等于XmlPullParser.END_DOCUMENT,说明解析工作还没有完成,调用next()方法来获取下一个事件进行解析。
- 在while 循环中,我们通过getName()方法得到当前节点的名字,如果发现节点名等于id、name或version,就可以调用nextText()方法来获取节点内的具体内容,每当解析完一个app节点后就将数据打印出来。
SAX解析
SAX解析是一种特别常用的XML解析方式,虽然它的用法比Pull解析要复杂一些,但在语义方面会更加的清楚。
首先我们要新建一个类继承DefaultHandler,并重写其中的5个方法。
public class MyHandler extends DefaultHandler{
@override
public void startDocument() throws SAXException{
}
@override
public void startElement(String uri,String localName,String qName,Attributes attributes)throws SAXException{
}
@override
publiv void characters(char[] ch,int start,int length)throws SAXException{
}
@override
public void endElement(String uri,String qName)throws SAXException{
}
@override
public void endDocument throws SAXException{
}
}
需要注意的是,在获取结点中内容时,characters()方法可能会被多次调用,一些换行符也被当做内容解析出来,我们需要针对这种情况在代码中做好控制。
示例
public class ContentHandler extends DefaultHandler{
private String nodeName;
private StringBuilder id;
private StringBuilder name;
private StringBuilder version;
@override
public void startDocument() throws SAXException{
id=new StringBuilder;
name=new StringBulider;
version=new StringBuilder;
}
@override
public void startElement(String uri,Attributes attributes)throws SAXException{
//记录当前结点名
nodeName=localName;
}
@override
publiv void characters(char[] ch,int length)throws SAXException{
//根据当前的结点名判断将内容添加到哪一个StringBuilder对象中
if("id".equals(nodeName)){
id.append(ch,start,length);
}else if("name".equals(nodeName)){
name.append(ch,length);
}else if("version".equals(nodeName)){
version.append(ch,length);
}
}
@override
public void endElement(String uri,String qName)throws SAXException{
if("app".equals(localName)){
Log.d("content","id is"+id.toString().trim());
Log.d("content","name is"+name.toString().trim());
Log.d("content","version is"+version.toString().trim());
//最后将StringBuilder清空掉
id.setLength(0);
name.setLength(0);
version.setLength(0);
}
@override
public void endDocument throws SAXException{
}
}
- 我们首先给id、name和version分别定义了一个StringBuilder对象,并在startDocument()方法里对它们进行了初始化。每当开始解析某个结点时,startElement()方法就会得到调用,其中localName参数记录着当前结点的名字,这里我们记录下来。
- 接着在解析结点中的具体内容的时候就会调用characters()方法,我们会根据当前的结点名进行判断,将解析出的内容添加到哪一个StringBuilder对象中。
- 最后在endElement()方法中进行判断,如果app已经解析完成,就会打印出来所有的内容。
- 需要注意的是,目前id、name和version中都可能是包括回车或者换行符的,因此在打印之前调用一下trim()方法,并且打印完后还要清空StringBuilder.
在接收到服务器返回的程序中调用
parseXMLWithSAX(response);
private void parseXMLWithSAX(String xmlData){
try{
SAXParserFactory factory=SAXParserFactory.newInstance();
XMLReader xmlReader=factory.newSAXParser().getXMLReader();
ContentHandler handler = new ContentHandler();
//将ContentHandler的实例设置到XMLReader中
xmlReader.setContentHandler(handler);
//开始执行解析
xmlReader.parse(new InputSource(new StringReader(xmlData)));
}catch(Exception e){
e.printStackTrace();
}
}
}
在得到了服务器的返回数据后,我们这次调用parseXMLWithSAX()方法来解析XML数据。parseXMLWithSAX()方法中先是创建了一个SAXParserFactory的对象,然后再获取到XMLReader对象,接着将我们编写的ContentHandler的实例设置到XMLReader中,最后调用parse()方法开始执行