PULL方式
除了可以使用?SAX和DOM解析XML文件曹锨,也可以使用Android內(nèi)置的Pull解析器解析XML文件。?Pull解析器的運行方式與?SAX? 解析器相似胁编。它也是事件觸發(fā)的华匾。Pull解析方式讓應(yīng)用程序完全控制文檔該怎么樣被解析构罗。比如開始和結(jié)束元素事件,使用parser.next()可以進入下一個元素并觸發(fā)相應(yīng)事件溪北。通過Parser.getEventType()方法來取得事件的代碼值桐绒,解析是在開始時就完成了大部分處理夺脾。事件將作為數(shù)值代碼被發(fā)送,因此可以使用一個switch對感興趣的事件進行處理茉继。
Pull解析是一個遍歷文檔的過程咧叭,每次調(diào)用next(),nextTag(),?nextToken()和nextText()都會向前推進文檔烁竭,并使Parser停留在某些事件上面菲茬,但是不能倒退。然后把文檔設(shè)置給Parser派撕。
Android中對Pull方法提供了支持的API婉弹,主要是
org.xmlpull.v1.XmlPullParser;?
org.xmlpull.v1.XmlPullParserFactory;?
二個類,其中主要使用的是XmlPullParser终吼,XmlPullParserFactory是一個工廠镀赌,用于構(gòu)建XmlPullParser對象。
應(yīng)用程序通過調(diào)用XmlPullParser.next()等方法來產(chǎn)生Event际跪,然后再處理Event商佛。
???????我們?nèi)匀荒蒙鲜鎏鞖忸A(yù)報的XML文件的一部分來做例子。
例如:需要解析的XML文件是:
[java]
<forecast_conditions>??
</forecast_conditions>??
這部分XML文件中day_of_week,low,high等是TAG垫卤,data是ATTRIBUTEA威彰。當然,如果有<></>夾在開始和結(jié)束符號之間的部分穴肘,則為TXET。
要想解析文檔先要構(gòu)建一個XmlPullParser對象舔痕。
[java]
final?XmlPullParserFactory?factory?=?XmlPullParserFactory.newInstance();???
factory.setNamespaceAware(true);???
final?XmlPullParser?parser?=?factory.newPullParser();???
parser.setInput(new?StringReader("xmlStr");??
這里的xmlStr就是上邊的XML文件评抚。
此時,文檔剛被初始化伯复,所以它應(yīng)該位于文檔的開始慨代,事件為START_DOCUMENT,可以通過XmlPullParser.getEventType()來獲取啸如。然后調(diào)用next()會產(chǎn)生
START_TAG侍匙,這個事件告訴應(yīng)用程序一個標簽已經(jīng)開始了,調(diào)用getName()會返回"?day_of_week?";若有TEXT叮雳,則再next()會產(chǎn)生TEXT事件想暗,調(diào)用getText()會返回TEXT,由于此處沒有帘不,所以再next()说莫,會產(chǎn)生END_TAG,這個告訴你一個標簽已經(jīng)處理完了寞焙,再next()直到最后處理完TAG储狭,會產(chǎn)生END_DOCUMENT互婿,它告訴你整個文檔已經(jīng)處理完成了。除了next() 外辽狈,nextToken()也可以使用慈参,只不過它會返回更加詳細的事件,比如COMMENT,?CDSECT,?DOCDECL,? ENTITY等等非常詳細的信息刮萌。如果程序得到比較底層的信息懂牧,可以用nextToken()來驅(qū)動并處理詳細的事件。需要注意一點的是TEXT事件是有可能返回空白的White?Spaces比如換行符或空格等尊勿。
nextTag()--會忽略White?Spaces僧凤,如果可以確定下一個是START_TAG或END_TAG,就可以調(diào)用nextTag()直接跳過去元扔。通常它有二個用處:當START_TAG時躯保,如果能確定這個TAG含有子TAG,那么就可以調(diào)用nextTag()產(chǎn)生子標簽的START_TAG事件澎语;當END_TAG時途事,如果確定不是文檔結(jié)尾,就可以調(diào)用nextTag()產(chǎn)生下一個標簽的START_TAG擅羞。在這二種情況下如果用next()會有TEXT事件尸变,但返回的是換行符或空白符。
nextText()--只能在START_TAG時調(diào)用减俏。當下一個元素是TEXT時召烂,TEXT的內(nèi)容會返回;當下一個元素是END_TAG時娃承,也就是說這個標簽的內(nèi)容為空奏夫,那么空字串返回;這個方法返回后历筝,Parser會停在END_TAG上酗昼。
核心代碼如下所示:
[java]
myPULL.setOnClickListener(new?Button.OnClickListener(){??
@Override??
public?void?onClick(View?v)?{??
try{??
String?url?="http://www.google.com/ig/api?&weather=beijing";??
DefaultHttpClient?client?=new?DefaultHttpClient();???
HttpUriRequest?req?=new?HttpGet(url);???
????????????????????HttpResponse?resp?=?client.execute(req);???
????????????????????HttpEntity?ent?=?resp.getEntity();???
InputStream?stream?=?ent.getContent();//將文件導(dǎo)入流,因此用InputStream??
????????????????????XmlPullParserFactory?factory?=?XmlPullParserFactory.newInstance();??
factory.setNamespaceAware(true);??
????????????????????XmlPullParser?xpp?=?factory.newPullParser();??
xpp.setInput(stream,null);??
//xpp.setInput(?new?StringReader?(?"<foo>Hello?World!</foo>"?)?);??
int?eventType?=?xpp.getEventType();??
while?(eventType?!=?XmlPullParser.END_DOCUMENT)?{??
if(eventType?==?XmlPullParser.START_DOCUMENT)?{??
System.out.println("Start?document");??
}else?if(eventType?==?XmlPullParser.START_TAG)?{??
System.out.println("Start?tag?"+xpp.getName());??
if(xpp.getName().equals("high")){??
????????????????????????????????j++;??
if(j==2){??
highestTmp.setText(String.valueOf((Integer.parseInt(xpp.getAttributeValue(0))-32)*5/9));?????????????????????????????
????????????????????????????????}??
????????????????????????????}??
}else?if(eventType?==?XmlPullParser.END_TAG)?{??
System.out.println("End?tag?"+xpp.getName());??
}else?if(eventType?==?XmlPullParser.TEXT)?{??
System.out.println("Text?"+xpp.getText());??
????????????????????????}??
????????????????????????eventType?=?xpp.next();??
????????????????????}??
System.out.println("End?document");??
????????????????????}??
catch(Exception?e){??
????????????????????????e.printStackTrace();??
????????????????????}??
????????????????}?????
????????????});???