在Android平台上可以使用Document Object Model(DOM)、Simple API for XML(SAX)和Android附带的pull解析器解析XML文件。
要解析的river.xml 如下:
<?xml version="1.0" encoding="utf-8"?>
<rivers>
<river name="灵渠" length="605">
<introduction>
灵渠在广西壮族自治区兴安县境内,是世界上最古老的运河之一,有着“世界古代水利建筑明珠”的美誉。灵渠古称秦凿渠、零渠、陡河、兴安运河,于公元前214年凿成通航,距今已2217年,仍然发挥着功用。
</introduction>
<imageurl>
http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
</imageurl>
</river>
<river name="胶莱运河" length="200">
<introduction>
胶莱运河南起黄海灵山海口,北抵渤海三山岛,流经现胶南、胶州、平度、高密、昌邑和莱州等,全长200公里,流域面积达5400平方公里,南北贯穿山东半岛,沟通黄渤两海。胶莱运河自平度姚家村东的分水岭南北分流。南流由麻湾口入胶州湾,为南胶莱河,长30公里。北流由海仓口入莱州湾,为北胶莱河,长100余公里。
</introduction>
<imageurl>
http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
</imageurl>
</river>
<river name="苏北灌溉总渠" length="168">
<introduction>
位于淮河下游江苏省北部,西起洪泽湖边的高良涧,流经洪泽,青浦、淮安,阜宁、射阳,滨海等六县(区),东至扁担港口入海的大型人工河道。全长168km。
</introduction>
<imageurl>
http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
</imageurl>
</river>
</rivers>
三种方式解析的结果是一样的,效果图如下:
下面附上代码:
1.River.java:
public class River {
private String name;
private int length;
private String introduction;
private String imageurl;
public River(){
}
public River(String name, int length, String introduction, String imageurl){
this.name = name;
this.length = length;
this.introduction = introduction;
this.imageurl = imageurl;
}
@Override
public String toString() {
return "River [name=" + name + ", length=" + length + ", introduction="
+ introduction + ", imageurl=" + imageurl + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public String getIntroduction() {
return introduction;
}
public void setIntroduction(String introduction) {
this.introduction = introduction;
}
public String getImageurl() {
return imageurl;
}
public void setImageurl(String imageurl) {
this.imageurl = imageurl;
}
}
2.MainActivity.java:
说明:定义了三个按钮和一个列表,并对三个按钮设置点击事件。
public class MainActivity extends Activity {
private Button domParserBt = null;
private Button saxParserBt = null;
private Button pullParserBt = null;
private ListView riverList = null;
private RiverAdapter riverAdapter = null;
private InputStream inputStream = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
domParserBt = (Button) findViewById(R.id.DOMParserBt);
saxParserBt = (Button) findViewById(R.id.SAXParserBt);
pullParserBt = (Button) findViewById(R.id.PULLParserBt);
riverList = (ListView) findViewById(R.id.lv);
inputStream = MainActivity.class.getClassLoader().getResourceAsStream("river.xml");
domParserBt.setOnClickListener(new DomParserButtonListener());
saxParserBt.setOnClickListener(new SaxParserButtonListener());
pullParserBt.setOnClickListener(new PullParserButtonListener());
}
private class DomParserButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
try {
List<River> rivers = XmlParserService
.getRiverListDomParser(inputStream);
riverAdapter = new RiverAdapter(MainActivity.this, rivers);
riverList.setAdapter(riverAdapter);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "xml解析失败", 0).show();
}
}
}
private class SaxParserButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
try {
List<River> rivers = XmlParserService
.getRiverListSaxParser(inputStream);
riverAdapter = new RiverAdapter(MainActivity.this, rivers);
riverList.setAdapter(riverAdapter);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "xml解析失败", 0).show();
}
}
}
private class PullParserButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
try {
List<River> rivers = XmlParserService
.getRiverListPullParser(inputStream);
riverAdapter = new RiverAdapter(MainActivity.this, rivers);
riverList.setAdapter(riverAdapter);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "xml解析失败", 0).show();
}
}
}
}
3.XmlParserService.java:
说明:包含三个方法,分别是每个按钮点击事件中调用的解析方法,而且由于方法不依赖类特定的实例,所以定义为静态类。
public class XmlParserService {
public static List<River> getRiverListDomParser(InputStream is) throws Exception{
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = documentBuilder.parse(is);
List<River> rivers = null;
River river = null;
//找到根Element
Element root = document.getDocumentElement();
NodeList nodes = root.getElementsByTagName("river");
rivers = new ArrayList<River>();
for (int i = 0; i < nodes.getLength(); i++) {
river = new River();
//获取river元素节点
Element riverElement = (Element) nodes.item(i);
//获取river中name和length属性值
river.setName(riverElement.getAttribute("name"));
river.setLength(Integer.parseInt(riverElement.getAttribute("length")));
//获取river下introduction标签
Element introductionElement = (Element) riverElement.getElementsByTagName("introduction").item(0);
river.setIntroduction(introductionElement.getFirstChild().getNodeValue());
//获取river下imageurl标签
Element imageurlElement = (Element) riverElement.getElementsByTagName("imageurl").item(0);
river.setImageurl(imageurlElement.getFirstChild().getNodeValue());
rivers.add(river);
}
is.close();
return rivers;
}
public static List<River> getRiverListSaxParser(InputStream is) throws Exception{
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxFactory.newSAXParser();
XmlContentHandler handler = new XmlContentHandler();
saxParser.parse(is, handler);
is.close();
return handler.getRivers();
}
public static List<River> getRiverListPullParser(InputStream is) throws Exception{
XmlPullParser pullParser = Xml.newPullParser();
pullParser.setInput(is, "utf-8");
List<River> rivers = null;
River river = null;
int type = pullParser.getEventType();
while(type != pullParser.END_DOCUMENT){
switch (type) {
case XmlPullParser.START_TAG:
if("rivers".equals(pullParser.getName())){
rivers = new ArrayList<River>();
}else if("river".equals(pullParser.getName())){
river = new River();
String name = pullParser.getAttributeValue(0);
int length = Integer.parseInt(pullParser.getAttributeValue(1));
river.setName(name);
river.setLength(length);
}else if("introduction".equals(pullParser.getName())){
String introduction = pullParser.nextText();
river.setIntroduction(introduction);
}else if("imageurl".equals(pullParser.getName())){
String imageurl = pullParser.nextText();
river.setImageurl(imageurl);
}
break;
case XmlPullParser.END_TAG:
if("river".equals(pullParser.getName())){
rivers.add(river);
}
break;
}
type = pullParser.next();
}
is.close();
return rivers;
}
}
4.XmlContentHandler.java:
说明:SAX解析方法使用了DefaultHandler,所以定义了次类继承DefaultHandler。
注意:下面代码中使用了StringBuffer,使用普通的方法在characters方法中处理标签的内容时,characters方法会调用多次,后来参考了http://blog.csdn.net/feng88724/article/details/7013675这片文章,才解决了问题。
public class XmlContentHandler extends DefaultHandler {
public static final String TAG = "XmlContentHandler";
private StringBuilder sb = new StringBuilder();
private List<River> rivers = null;
private River river = null;
public List<River> getRivers() {
return rivers;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
Log.i(TAG, "解析内容:" + new String(ch, start, length));
sb.append(ch, start, length);
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
Log.i(TAG, "文档解析完毕。");
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
Log.i(TAG, localName + "解析完毕");
String content = sb.toString();
if ("river".equals(localName)) {
rivers.add(river);
}if(("introduction").equals(localName)){
river.setIntroduction(content);
}else if(("imageurl").equals(localName)){
river.setImageurl(content);
}
}
@Override
public void startDocument() throws SAXException {
Log.i(TAG, "开始解析... ...");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
Log.i(TAG, "解析元素:" + localName);
if (localName.equals("rivers")) {
rivers = new ArrayList<River>();
} else if (localName.equals("river")) {
river = new River();
river.setName(attributes.getValue(0));
river.setLength(Integer.parseInt(attributes.getValue(1)));
}
sb.setLength(0);
}
}
5.RiverAdapter.java:
public class RiverAdapter extends BaseAdapter{
private LayoutInflater mInflater;
private List<River> riverList = Collections.emptyList();
public RiverAdapter(Context context, List<River> riverList){
this.mInflater = LayoutInflater.from(context);
this.riverList = riverList;
}
@Override
public int getCount() {
return riverList.size();
}
@Override
public Object getItem(int position) {
return riverList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(R.layout.river_item, null);
RiverHolder riverHolder = new RiverHolder();
riverHolder.riverName = (TextView) convertView.findViewById(R.id.river_name);
riverHolder.riverLength = (TextView) convertView.findViewById(R.id.river_length);
riverHolder.riverIntroduction = (TextView) convertView.findViewById(R.id.river_introduction);
River river = riverList.get(position);
if(river != null){
riverHolder.riverName.setText(river.getName());
riverHolder.riverLength.setText(river.getLength() + "");
riverHolder.riverIntroduction.setText(river.getIntroduction());
}
return convertView;
}
public class RiverHolder{
public TextView riverName;
public TextView riverLength;
public TextView riverIntroduction;
}
}