XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setContentHandler(new InfoXMLHander());
reader.parse(new InputSource(getResources().getAssets().open("info.xml")));
其中InfoXMLHander是继承DefaultHandler子类,主要实现characters,startElement,endElement方法来实现xml文件解析。
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;
}
}
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;
}
}