1. XML解析有3中方式:
[1] DOM方式 把整个XML文档读入内存中,再DOM API来访问树形结构,获取数据; 缺点:文档很大时,消耗较多内存。
[2] SAX方式 基于事件驱动的,单向读取,优点:不占内存空间、解析属性方便,但缺点就是对于套嵌多个分支来说处理不是很方便。
[3] PULL方式 PULL常常用在J2ME对于节点处理比较好,类似SAX方式,同样很节省内存。
2. 首先需要解析的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>
3.RiverModel代码如下:
package com.testxml.demo; import java.io.Serializable; public class RiverModel implements Serializable { public static final String RIVERS = "rivers"; public static final String RIVER = "river"; public static final String LENGTH = "length"; public static final String NAME = "name"; public static final String IMGURL = "imageurl"; public static final String INTRODUCTION = "introduction"; private int length; private String name; private String imgUrl; private String introduction; public int getLength() { return length; } public void setLength(int length) { this.length = length; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImgUrl() { return imgUrl; } public void setImgUrl(String imgUrl) { this.imgUrl = imgUrl; } public String getIntroduction() { return introduction; } public void setIntroduction(String introduction) { this.introduction = introduction; } }
4.activity代码如下:
package com.testxml.demo; import java.util.ArrayList; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class ParseXMLActivity extends Activity implements OnClickListener { private Button mButtonDOM; private Button mButtonSAX; private Button mButtonPULL; private TextView mTextView; private ArrayList<RiverModel> rivers = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initViews(); initControl(); } private void initViews() { mButtonDOM = (Button) findViewById(R.id.btn_dom); mButtonSAX = (Button) findViewById(R.id.btn_sax); mButtonPULL= (Button) findViewById(R.id.btn_pull); mTextView = (TextView) findViewById(R.id.txt_content); } private void initControl() { mButtonDOM.setOnClickListener(this); mButtonSAX.setOnClickListener(this); mButtonPULL.setOnClickListener(this); } @Override public void onClick(View v) { int id = v.getId(); switch (id) { case R.id.btn_dom: rivers = (ArrayList<RiverModel>) XMLHelper.DOMMannerParse(this, "test.xml"); String s = ""; for(RiverModel rm:rivers) { s += "DOM: name:"+rm.getName()+", length:"+rm.getLength()+"\n info:"+rm.getIntroduction()+"\n"; } mTextView.setText(s); break; case R.id.btn_pull: rivers = (ArrayList<RiverModel>) XMLHelper.DOMMannerParse(this, "test.xml"); String s1 = ""; for(RiverModel rm:rivers) { s1 += "PULL: name:"+rm.getName()+", length:"+rm.getLength()+"\n info:"+rm.getIntroduction()+"\n"; } mTextView.setText(s1); break; case R.id.btn_sax: rivers = (ArrayList<RiverModel>) XMLHelper.SAXParseXML(this, "test.xml"); String s2 = ""; for(RiverModel rm:rivers) { s2 += "SAX: name:"+rm.getName()+", length:"+rm.getLength()+"\n info:"+rm.getIntroduction()+"\n"; } mTextView.setText(s2); break; default: break; } } }
5.XMLHelper类实现3种方式解析XML代码如下:
package com.testxml.demo; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; import android.util.Xml; public class XMLHelper { // DOM方式解析 把整个XML文档读入内存中,再DOM API来访问树形结构,获取数据; 缺点:文档很大时,消耗很多内存 public static List<RiverModel> DOMMannerParse(Context context, String fileName) { List<RiverModel> rivers = new ArrayList<RiverModel>(); DocumentBuilderFactory factory = null; DocumentBuilder builder = null; Document document = null; InputStream inputStream = null; factory = DocumentBuilderFactory.newInstance(); try { builder = factory.newDocumentBuilder(); inputStream = context.getResources().getAssets().open(fileName); document = builder.parse(inputStream); Element root = document.getDocumentElement(); // 解析子节点 NodeList nodeList = root.getElementsByTagName(RiverModel.RIVER); RiverModel riverModel = null; for (int i = 0; i < nodeList.getLength(); i++) { riverModel = new RiverModel(); Element riverElement = (Element) nodeList.item(i); riverModel.setName(riverElement.getAttribute(RiverModel.NAME)); riverModel.setLength(Integer.parseInt(riverElement .getAttribute(RiverModel.LENGTH))); // 解析子节点 Element introduction = (Element) riverElement .getElementsByTagName(RiverModel.INTRODUCTION).item(0); riverModel.setIntroduction(introduction.getFirstChild() .getNodeValue()); Element imgurl = (Element) riverElement.getElementsByTagName( RiverModel.IMGURL).item(0); riverModel.setImgUrl(imgurl.getFirstChild().getNodeValue()); rivers.add(riverModel); } } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (Exception e) { e.printStackTrace(); } } return rivers; } // PULL方式解析 public static List<RiverModel> PULLParseXML(Context context, String fileName) { List<RiverModel> rivers = new ArrayList<RiverModel>(); RiverModel riverModel = null; InputStream inputStream = null; XmlPullParser xmlPullParser = Xml.newPullParser(); try { inputStream = context.getResources().getAssets().open(fileName); xmlPullParser.setInput(inputStream, "utf-8"); int evtType = xmlPullParser.getEventType(); while (evtType != XmlPullParser.END_DOCUMENT) { switch (evtType) { case XmlPullParser.START_TAG: String tag = xmlPullParser.getName(); if (tag.equalsIgnoreCase(RiverModel.RIVER)) { riverModel = new RiverModel(); riverModel.setName(xmlPullParser.getAttributeValue( null, RiverModel.NAME)); riverModel.setLength(Integer.parseInt(xmlPullParser .getAttributeValue(null, RiverModel.LENGTH))); } // 如果是解析子节点 else if (riverModel != null) { if (tag.equalsIgnoreCase(RiverModel.INTRODUCTION)) { riverModel .setIntroduction(xmlPullParser.nextText()); } else if (tag.equalsIgnoreCase(RiverModel.IMGURL)) { riverModel.setImgUrl(xmlPullParser.nextText()); } } break; case XmlPullParser.END_TAG: // 当碰到river结束时,添加RiverModel进rivers中去 if (xmlPullParser.getName().equalsIgnoreCase( RiverModel.RIVER) && riverModel != null) { rivers.add(riverModel); riverModel = null; } break; default: break; } } } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return rivers; } // SAX方式解析 public static List<RiverModel> SAXParseXML(Context context, String fileName) { List<RiverModel> rivers = null; SAXParserFactory factory = SAXParserFactory.newInstance(); try { SAXParser parser = factory.newSAXParser(); XMLReader xmlReader = parser.getXMLReader(); MyContentHandler handler = new MyContentHandler(); xmlReader.setContentHandler(handler); xmlReader.parse(new InputSource(context.getResources().getAssets() .open(fileName))); rivers = handler.getRivers(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return rivers; } static class MyContentHandler extends DefaultHandler { private boolean isRiver = false; private boolean isIntroduction = false; private boolean isImageUrl = false; private RiverModel riverModel = null; private List<RiverModel> rivers = new ArrayList<RiverModel>(); public List<RiverModel> getRivers() { return rivers; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { String tagName = localName.length() != 0 ? localName : qName; tagName = tagName.toLowerCase().trim(); if (tagName.equals(RiverModel.RIVER)) { isRiver = true; riverModel = new RiverModel(); riverModel.setName(attributes.getValue(RiverModel.NAME)); riverModel.setLength(Integer.parseInt(attributes .getValue(RiverModel.LENGTH))); } if (isRiver) { if (tagName.equals(RiverModel.INTRODUCTION)) { isIntroduction = true; } else if (tagName.equals(RiverModel.IMGURL)) { isImageUrl = true; } } // super.startElement(uri, localName, qName, attributes); } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (isIntroduction) { riverModel .setIntroduction(riverModel.getIntroduction() == null ? new String( ch, start, length) : riverModel .getIntroduction() + new String(ch, start, length)); } else if (isImageUrl) { riverModel .setImgUrl(riverModel.getImgUrl() == null ? new String( ch, start, length) : riverModel.getImgUrl() + new String(ch, start, length)); } // super.characters(ch, start, length); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { String tagName = localName.length() != 0 ? localName : qName; tagName = tagName.toLowerCase().trim(); if (tagName.equals(RiverModel.RIVER)) { isRiver = true; rivers.add(riverModel); } if (isRiver) { if (tagName.equals(RiverModel.INTRODUCTION)) { isIntroduction = false; } else if (tagName.equals(RiverModel.IMGURL)) { isImageUrl = false; } } // super.endElement(uri, localName, qName); } } }