Android(安卓)XML 解析
16lz
2021-12-04
参考http://www.cnblogs.com/devinzhang/archive/2012/01/16/2323668.html
自己做一下,可以加深理解。
需要解析的XML如下:
<?xml version="1.0" encoding="utf-8"?><books><book><name>水浒传</name><price value = "45"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic1.jpg"></pic></book><book><name>希腊神话</name><price value = "36"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic2.jpg"></pic></book><book><name>励志中国</name><price value = "68"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic3.jpg"></pic></book><book><name>培根随笔</name><price value = "50"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic4.jpg"></pic></book><book><name>海底两万里</name><price value = "48"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic5.jpg"></pic></book><book><name>百年孤独</name><price value = "63"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic6.jpg"></pic></book><book><name>童年.在人间.我的大学</name><price value = "48"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic7.jpg"></pic></book><book><name>青鸟</name><price value = "24"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic8.jpg"></pic></book><book><name>茶花女</name><price value = "38"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic9.jpg"></pic></book><book><name>哲理文学名著</name><price value = "96"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic10.jpg"></pic></book><book><name>老人与海</name><price value = "69"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic11.jpg"></pic></book><book><name>文学名著赏析</name><price value = "78"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic12.jpg"></pic></book><book><name>三国演义</name><price value = "69"></price><pic url="http://192.168.8.14:8080/MyOrders/image/pic13.jpg"></pic></book></books>
代码如下:
package com.test.vbo; import android.net.Uri; import android.util.Log; import android.util.Xml; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; 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; public class BookParser { public static final int MODE_SAX = 0; public static final int MODE_DOM = 1; public static final int MODE_PULL = 2; private static final String TAG = "BookParser"; public List<Book> parse(InputStream input, int mode) { switch (mode) { case MODE_SAX: return parseBySax(input); case MODE_DOM: return parseByDom(input); case MODE_PULL: return parseByPull(input); default : throw new IllegalArgumentException("Unsupported mode " + mode); } } //1. SAX解析XML文件 /*SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。 * SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档, * 在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分, * 如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法, * 这些方法(事件)定义在ContentHandler接口。 */ private List<Book> parseBySax(InputStream input) { List<Book> result = null; try { //创建解析器 SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); //设置解析器的相关特性,true表示开启命名空间特性 //saxParser.setProperty("http://xml.org/sax/features/namespaces",true); XMLContentHandler handler = new XMLContentHandler(); saxParser.parse(input, handler); result = handler.getBooks(); } catch (Exception e) { Log.w(TAG, "during parse by sax", e); } return result; } //SAX类:DefaultHandler,它实现了ContentHandler接口。在实现的时候,只需要继承该类,重载相应的方法即可。 private class XMLContentHandler extends DefaultHandler { private List<Book> mBooks = null; private Book mCurrentBook; private String mTagName = null;// 当前解析的元素标签 public List<Book> getBooks() { return mBooks; } // 接收文档开始的通知。当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。 @Override public void startDocument() throws SAXException { //mBooks = new ArrayList<Book>(); } // 接收元素开始的通知。当读到一个开始标签的时候,会触发这个方法。其中namespaceURI表示元素的命名空间; // localName表示元素的本地名称(不带前缀);qName表示元素的限定名(带前缀);atts 表示元素的属性集合 @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { if ("books".equals(localName)) { mBooks = new ArrayList<Book>(); } else if ("book".equals(localName)) { mCurrentBook = new Book(); } else if ("price".equals(localName)) { mCurrentBook.setPrice(Float.parseFloat(atts.getValue("value"))); } else if ("pic".equals(localName)) { mCurrentBook.setPic(Uri.parse(atts.getValue("url"))); } mTagName = localName; } // 接收字符数据的通知。该方法用来处理在XML文件中读到的内容,第一个参数用于存放文件的内容, // 后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。 @Override public void characters(char[] ch, int start, int length) throws SAXException { if (mTagName != null) { String data = new String(ch, start, length); if (mTagName.equals("name")) { mCurrentBook.setName(data); } } } // 接收文档的结尾的通知。在遇到结束标签的时候,调用这个方法。其中,uri表示元素的命名空间; // localName表示元素的本地名称(不带前缀);name表示元素的限定名(带前缀) @Override public void endElement(String uri, String localName, String name) throws SAXException { if (localName.equals("book")) { mBooks.add(mCurrentBook); mCurrentBook = null; } mTagName = null; } } //2. DOM解析XML文件 /* * DOM解析XML文件时,会将XML文件的所有内容读取到内存中, * 然后允许您使用DOM API遍历XML树、检索所需的数据。 * 使用DOM操作XML的代码看起来比较直观,并且,在某些方面比基于SAX的实现更加简单。 * 但是,因为DOM需要将XML文件的所有内容读取到内存中,所以内存的消耗比较大, * 特别对于运行Android的移动设备来说,因为设备的资源比较宝贵, * 所以建议还是采用SAX来解析XML文件,当然,如果XML文件的内容比较小采用DOM是可行的。 */ private List<Book> parseByDom(InputStream input) { List<Book> books = new ArrayList<Book>(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder = factory.newDocumentBuilder(); Document dom = builder.parse(input); Element root = dom.getDocumentElement(); NodeList items = root.getElementsByTagName("book");// 查找所有book节点 for (int i = 0; i < items.getLength(); i++) { Book book = new Book(); // 得到第i个book节点 Element bookNode = (Element) items.item(i); // 获取book节点下的所有子节点 NodeList childsNodes = bookNode.getChildNodes(); for (int j = 0; j < childsNodes.getLength(); j++) { Node node = childsNodes.item(j); String nodeName = node.getNodeName(); if ("name".equals(nodeName)) { book.setName(node.getFirstChild().getNodeValue()); } else if ("price".equals(nodeName)){ Element priceNode = ((Element) node); book.setPrice(Float.parseFloat(priceNode.getAttribute("value"))); } else if ("pic".equals(nodeName)) { Element picNode = ((Element) node); book.setPic(Uri.parse(picNode.getAttribute("url"))); } } books.add(book); } } catch (ParserConfigurationException e) { Log.w(TAG, "during parse by dom newDocumentBuilder ", e); } catch (SAXException e) { Log.w(TAG, "during parse by dom parse", e); e.printStackTrace(); } catch (IOException e) { Log.w(TAG, "during parse by dom parse", e); e.printStackTrace(); } return books; } //3.Pull解析器解析XML文件 /* * Pull解析器的运行方式与 SAX 解析器相似。 * 它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。 * 事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。 * 当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型元素的值。 */ private List<Book> parseByPull(InputStream input) { XmlPullParser parser = Xml.newPullParser(); Book currentBook = null; List<Book> books = null; try { parser.setInput(input, "UTF-8"); int eventType = parser.getEventType(); while (XmlPullParser.END_DOCUMENT != eventType) { switch (eventType) { case XmlPullParser.START_DOCUMENT: break; case XmlPullParser.START_TAG: String tagName = parser.getName(); if ("books".equals(tagName)) { books = new ArrayList<Book>(); } else if ("book".equals(tagName)){ currentBook = new Book(); } else if (currentBook != null) { if ("name".equals(tagName)) { currentBook.setName(parser.nextText()); } else if ("price".equals(tagName)){ currentBook.setPrice(Float.parseFloat(parser.getAttributeValue(null, "value"))); } else if ("pic".equals(tagName)) { currentBook.setPic(Uri.parse(parser.getAttributeValue(null, "url"))); } } break; case XmlPullParser.END_TAG: if (currentBook != null && "book".equals(parser.getName())) { books.add(currentBook); currentBook = null; } break; } eventType = parser.next(); } } catch (XmlPullParserException e) { Log.w(TAG, "during parse by pull set input", e); } catch (IOException e) { Log.w(TAG, "during parse by pull next", e); } return books; } }
已知数据,创建Xml的代码如下:
public class XmlWriter { private static final String TAG = "XmlWriter"; public static final int FLAG_WRITE_TO_FILE = 0; public static final int FLAG_WRITE_TO_STRING = 1; public static String write(List<Book> books, String path, int flag) { String result = null; XmlSerializer serializer = Xml.newSerializer(); File xmlFile = new File(path); try { Writer writer = null; switch (flag) { case FLAG_WRITE_TO_FILE: FileOutputStream outStream = new FileOutputStream(xmlFile); OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream, "UTF-8"); writer = new BufferedWriter(outStreamWriter); break; case FLAG_WRITE_TO_STRING: writer = new StringWriter(); break; default: throw new IllegalArgumentException("unsupport flag" + flag); } serializer.setOutput(writer); serializer.startDocument("UTF-8", true); serializer.startTag(null, "books"); for (Book book : books) { serializer.startTag(null, "book"); serializer.startTag(null, "name"); serializer.text(book.getName()); serializer.endTag(null, "name"); serializer.startTag(null, "price"); serializer.attribute(null, "value", book.getPrice() + ""); serializer.endTag(null, "price"); serializer.startTag(null, "price"); serializer.attribute(null, "url", book.getPic().toString()); serializer.endTag(null, "price"); serializer.endTag(null, "book"); } serializer.endTag(null, "books"); serializer.endDocument(); switch (flag) { case FLAG_WRITE_TO_FILE: writer.flush(); writer.close(); break; case FLAG_WRITE_TO_STRING: result = writer.toString(); break; default: throw new IllegalArgumentException("unsupport flag" + flag); } } catch (FileNotFoundException e) { Log.w(TAG, "during write xml file", e); } catch (UnsupportedEncodingException e) { Log.w(TAG, "during write xml file", e); } catch (IllegalArgumentException e) { Log.w(TAG, "during write xml file", e); } catch (IllegalStateException e) { Log.w(TAG, "during write xml file", e); } catch (IOException e) { Log.w(TAG, "during write xml file", e); } return result; }}
更多相关文章
- Android(安卓)Studio 运行模拟器启动失败
- android adb shell 命令大全
- Android(安卓)之读取元素中的数据
- android中如何获取文件的路径总结
- 如何在Android中使用OpenCV
- Android多国语言文件夹命名
- Android(安卓)读取元素中的数据
- Android在SDcard建文件夹(在Android中移动文件必用)
- adb shell命令大全