XML的解析與生成
Android平臺(tái)上可以使用 Simple API for XML (SAX), Document Object Model(DOM) 和Android 附帶的pull解析器 解析XML文件
眾所周知,,DOM解析方式很耗內(nèi)存, 優(yōu)先使用SAX或者pull
SAX:
解析速度快,占用內(nèi)存少,采用事件驅(qū)動(dòng),即不需要加載完整個(gè)文檔,而是按內(nèi)容順序解析文檔,在此過程中,其會(huì)判斷當(dāng)前讀到的內(nèi)容是否符合XML語法定義,如果符合就會(huì)觸發(fā)事件,所謂事件,其實(shí)就是一些callback方法,具體方法含義比較簡單, 看文檔即可,定義在DefaultHandler接口中(SAX已內(nèi)置到JDK5.0中)
待解析xml文件musics.xml:
- <?xml version="1.0" encoding="utf-8"?>
- <musics>
- <music id="1">
- <name>黑色幽默</name>
- <albumName>Jay</albumName>
- <year>2000</year>
- </music>
- <music id="2">
- <name>愛在西元前</name>
- <albumName>范特西</albumName>
- <year>2001</year>
- </music>
- <music id="3">
- <name>回到過去</name>
- <albumName>八度空間</albumName>
- <year>2002</year>
- </music>
- <music id="4">
- <name>東風(fēng)破</name>
- <albumName>葉惠美</albumName>
- <year>2003</year>
- </music>
- <music id="5">
- <name>七里香</name>
- <albumName>七里香</albumName>
- <year>2004</year>
- </music>
- <music id="6">
- <name>一路向北</name>
- <albumName>十一月的蕭邦</albumName>
- <year>2005</year>
- </music>
- </musics>
實(shí)體類MusicEntity就不貼了,四個(gè)屬性,上面的xml中也可以看出.
實(shí)現(xiàn)了DefaultHandler接口的SaxHandler:
- public class SaxHandler extends DefaultHandler{
- private static final String TAG = "lanyan";
- private List<MusicEntity> musics;
- private MusicEntity music;
- //緩存上一次的標(biāo)簽名
- private String preTag;
- @Override
- public void startDocument() throws SAXException {
- musics = new ArrayList<MusicEntity>();
- }
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
- if ("music".equals(localName)) {
- music = new MusicEntity();
- music.setId(Integer.parseInt(attributes.getValue("id")));
- }
- preTag = localName;
- }
- /**
- * 解析到文檔中字符內(nèi)容時(shí)調(diào)用
- * 所以一般網(wǎng)絡(luò)中傳輸?shù)膞ml,其父節(jié)點(diǎn)與子節(jié)點(diǎn)之間是緊挨在一起的,基本上就是一行,看起來很混亂,其實(shí)是為了避免解析時(shí)無必要的調(diào)用
- * 這里僅是測試,故忽略這個(gè)因素
- */
- @Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- if (null != music) {
- String str = new String(ch, start, length);
- if ("name".equals(preTag)) {
- music.setName(str);
- } else if ("albumName".equals(preTag)) {
- music.setAlbumName(str);
- } else if ("year".equals(preTag)) {
- music.setYear(Integer.parseInt(str));
- }
- }
- }
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- if ("music".equals(localName) && null != music) {
- musics.add(music);
- music = null;
- }
- preTag = null;
- }
- @Override
- public void endDocument() throws SAXException {
- }
- public List<MusicEntity> getMusics() {
- return musics;
- }
- }
對外提供SAX解析服務(wù)的接口SaxService:
- public class SaxService {
- public static List<MusicEntity> readXml(InputStream is) throws Exception {
- SAXParserFactory saxFactory = SAXParserFactory.newInstance();
- SAXParser parser = saxFactory.newSAXParser();
- // parser.setProperty("http://xml.org/sax/features/namespaces", true);
- SaxHandler handler = new SaxHandler();
- parser.parse(is, handler);
- return handler.getMusics();
- }
- }
測試方法:
- public void testSaxRead() {
- InputStream is = XmlPaserTest.class.getClassLoader().getResourceAsStream("musics.xml");
- try {
- List<MusicEntity> musics = SaxService.readXml(is);
- for (MusicEntity music : musics) {
- Log.i("lanyan", music.toString());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
Pull:
同樣是事件驅(qū)動(dòng),不同的是不需要實(shí)現(xiàn)什么handler接口,標(biāo)簽之間value的讀取也不需要通過類似characters(...)的回調(diào)方法,相關(guān)API已經(jīng)封轉(zhuǎn)好了
對外提供PULL解析服務(wù)的接口PullService中的xml解析方法:
- public static List<MusicEntity> readXml(InputStream is) throws Exception {
- List<MusicEntity> musics = null;
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(is, "UTF-8");
- int eventCode = parser.getEventType();// 事件類型
- MusicEntity music = null;
- while (eventCode != XmlPullParser.END_DOCUMENT) {
- switch (eventCode) {
- case XmlPullParser.START_DOCUMENT:// 開始文檔事件
- musics = new ArrayList<MusicEntity>();
- break;
- case XmlPullParser.START_TAG:// 元素開始標(biāo)志
- if ("music".equals(parser.getName())) {
- music = new MusicEntity();
- music.setId(new Integer(parser.getAttributeValue(0)));
- } else if (music != null) {
- if ("name".equals(parser.getName())) {
- music.setName(parser.nextText());// 拿到標(biāo)簽后***個(gè)文本節(jié)點(diǎn)的value
- } else if ("albumName".equals(parser.getName())) {
- music.setAlbumName(parser.nextText());
- } else if ("year".equals(parser.getName())) {
- music.setYear(Integer.parseInt(parser.nextText()));
- }
- }
- break;
- case XmlPullParser.END_TAG://元素結(jié)束標(biāo)志
- if ("music".equals(parser.getName()) && music != null) {
- musics.add(music);
- music = null;
- }
- break;
- }
- eventCode = parser.next();
- }
- return musics;
- }
使用PULL解析方式生成xml文件:
PullService中的xml生成方法:
- /**
- * Pull生成xml數(shù)據(jù)
- * @param persons
- * @param writer
- * @throws Exception
- */
- public static void writeXml(List<MusicEntity> musics, Writer writer)
- throws Exception {
- XmlSerializer serializer = Xml.newSerializer();
- serializer.setOutput(writer);
- serializer.startDocument("UTF-8", true);
- serializer.startTag(null, "musics");
- for (MusicEntity music : musics) {
- serializer.startTag(null, "music");
- serializer.attribute(null, "id", String.valueOf(music.getId()));
- serializer.startTag(null, "name");
- serializer.text(music.getName());
- serializer.endTag(null, "name");
- serializer.startTag(null, "albumName");
- serializer.text(music.getAlbumName());
- serializer.endTag(null, "albumName");
- serializer.startTag(null, "year");
- serializer.text(String.valueOf(music.getYear()));
- serializer.endTag(null, "year");
- serializer.endTag(null, "music");
- }
- serializer.endTag(null, "musics");
- serializer.endDocument();
- writer.flush();
- writer.close();
- }
測試方法:
- public void testPullWrite() throws Exception {
- List<MusicEntity> musics = new ArrayList<MusicEntity>();
- MusicEntity music1 = new MusicEntity();
- music1.setId(1);
- music1.setName("七里香");
- music1.setAlbumName("七里香");
- music1.setYear(2004);
- musics.add(music1);
- MusicEntity music2 = new MusicEntity();
- music2.setId(1);
- music2.setName("一路向北");
- music2.setAlbumName("十一月的蕭邦");
- music2.setYear(2005);
- musics.add(music2);
- //寫入文件
- // File file = new File(Environment.getExternalStorageDirectory(), "musics.xml");
- // BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
- //以字符串形式輸出
- StringWriter writer = new StringWriter();
- PullService.writeXml(musics, writer);
- Log.i("lanyan", writer.toString());
- }
輸出結(jié)果:
- <?xml version='1.0' encoding='UTF-8' standalone='yes' ?><musics><music id="1"><name>七里香</name><albumName>七里香</albumName><year>2004</year></music><music id="1"><name>一路向北</name><albumName>十一月的蕭邦</albumName><year>2005</year></music></musics>
原文鏈接:http://www.cnblogs.com/youjun/archive/2012/08/16/2641101.html
【編輯推薦】