在网络上传输数据时最常用的格式有两种,XML和JSON,下面我们就来一个个地进行学习,本节首先学一下如何解析XML格式的数据。
1.assets文件夹下放books.xml,里面放需要解析的xml数据
<?xml version="1.0" encoding="utf-8"?>
<books>
<book>
<id>1001</id>
<name>Thinking In Java</name>
<price>80.00</price>
</book>
<book>
<id>1002</id>
<name>Core Java</name>
<price>90.00</price>
</book>
<book>
<id>1003</id>
<name>Hello, Andriod</name>
<price>100.00</price>
</book>
</books>
2.Book实体类
public class Book {
private int id;
private String name;
private float price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
@Override
public String toString() {
return "Book [id=" + id + ", name=" + name + ", price=" + price + "]";
}
}
3.定义一个接口
public interface BookParser {
/**
* 解析输入流 得到Book对象集合
* @param is
* @return
* @throws Exception
*/
public List<Book> parse(InputStream is) throws Exception;
}
4.SAX解析
public class SAXParser implements BookParser {
@Override
public List<Book> parse(InputStream is) throws Exception {
// TODO Auto-generated method stub
SAXParserFactory factory = SAXParserFactory.newInstance(); // 取得SAXParserFactory实例
javax.xml.parsers.SAXParser parser = factory.newSAXParser(); // 从factory获取SAXParser实例
MyHandler handler = new MyHandler(); // 实例化自定义Handler
parser.parse(is, handler); // 根据自定义Handler规则解析输入流
return handler.getBooks();
}
// 需要重写DefaultHandler的方法
private class MyHandler extends DefaultHandler {
private List<Book> books;
private Book book;
private StringBuilder builder;
// 返回解析后得到的Book对象集合
public List<Book> getBooks() {
return books;
}
/*
* startDocument()方法会在开始XML解析的时候调用
*/
@Override
public void startDocument() throws SAXException {
super.startDocument();
books = new ArrayList<Book>();
builder = new StringBuilder();
}
/*
* startElement()方法会在开始解析某个结点的时候调用
* 其中,startElement()、characters()和endElement()这三个方法是有参数的,
* 从XML中解析出的数据就会以参数的形式传入到这些方法中。需要注意的是,在获取结点中的内容时,
* characters()方法可能会被调用多次,一些换行符也被当作内容解析出来,
* 我们需要针对这种情况在代码中做好控制。
*/
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if (localName.equals("book")) {
book = new Book();
}
builder.setLength(0); // 将字符长度设置为0 以便重新开始读取元素内的字符节点
}
/*
* characters()方法会在获取结点中内容的时候调用
*/
public void characters(char[] ch, int start, int length)
throws SAXException {
super.characters(ch, start, length);
builder.append(ch, start, length); // 将读取的字符数组追加到builder中
}
/*
* endElement()方法会在完成解析某个结点的时候调用
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
if (localName.equals("id")) {
book.setId(Integer.parseInt(builder.toString()));
} else if (localName.equals("name")) {
book.setName(builder.toString());
} else if (localName.equals("price")) {
book.setPrice(Float.parseFloat(builder.toString()));
} else if (localName.equals("book")) {
books.add(book);
}
}
/*
*endDocument()方法会在完成整个XML解析的时候调用
*/
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
}
}
}
5.PULL解析
public class PullParser implements BookParser{
@Override
public List<Book> parse(InputStream is) throws Exception {
// TODO Auto-generated method stub
List<Book> books=null;
Book book=null;
XmlPullParser parser=Xml.newPullParser();//由android.util.Xml创建一个XmlPullParser实例
parser.setInput(is, "utf-8"); //设置输入流 并指明编码方式
// parser.setInput(new StringReader("string")); //解析字符串
int eventType= parser.getEventType();
while(eventType!=XmlPullParser.END_DOCUMENT){
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
books=new ArrayList<Book>();
break;
//在一个while循环中不断地进行解析,如果当前的解析事件不等于XmlPullParser.END_DOCUMENT,说明解析工作还没完成,调用next()方法后可以获取下一个解析事件。
//在while循环中,我们通过getName()方法得到当前结点的名字,如果发现结点名等于id、name或version,就调用nextText()方法来获取结点内具体的内容
case XmlPullParser.START_TAG:// 开始解析某个结点
if(parser.getName().equals("book")){
book=new Book();
}else if(parser.getName().equals("id")){
//方法一:
eventType=parser.next();
book.setId(Integer.parseInt(parser.getText()));
}else if(parser.getName().equals("name")){
//方法二:
book.setName(parser.nextText());
}else if(parser.getName().equals("price")){
eventType=parser.next();
book.setPrice(Float.parseFloat(parser.getText()));
}
break;
case XmlPullParser.END_TAG:// 结束解析某个结点
if(parser.getName().equals("book")){
books.add(book);
book=null;
}
break;
}
eventType=parser.next();//这句不能少,否则会一直解析
}
return books;
}
}
6.DOM解析
public class DOMParser implements BookParser {
@Override
public List<Book> parse(InputStream is) throws Exception {
// TODO Auto-generated method stub
List<Book> books = new ArrayList<Book>();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 取得DocumentBuilderFactory实例
DocumentBuilder builder = factory.newDocumentBuilder(); // 从factory获取DocumentBuilder实例
Document doc = builder.parse(is); // 解析输入流 得到Document实例
Element rootElement = doc.getDocumentElement();
NodeList items = rootElement.getElementsByTagName("book");
for (int i = 0; i < items.getLength(); i++) {
Book book = new Book();
Node item = items.item(i);
NodeList properties = item.getChildNodes();
for (int j = 0; j < properties.getLength(); j++) {
Node property = properties.item(j);
String nodeName = property.getNodeName();
if (nodeName.equals("id")) {
book.setId(Integer.parseInt(property.getFirstChild()
.getNodeValue()));
} else if (nodeName.equals("name")) {
book.setName(property.getFirstChild().getNodeValue());
} else if (nodeName.equals("price")) {
book.setPrice(Float.parseFloat(property.getFirstChild()
.getNodeValue()));
}
}
books.add(book);
}
return books;
}
}
7.Activity中调用各个解析方法,解析xml数据
public class MainActivity extends Activity implements OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.pull).setOnClickListener(this);
findViewById(R.id.sax).setOnClickListener(this);
findViewById(R.id.dom).setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.pull:
try {
InputStream in= getAssets().open("books.xml");
PullParser parser=new PullParser();
try {
List<Book> books=parser.parse(in);
for(Book book:books){
Log.d("book",book.toString() );
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case R.id.dom:
InputStream inp=null;
try {
inp = getAssets().open("books.xml");
DOMParser parser=new DOMParser();
List<Book> books=parser.parse(inp);
for(Book book:books){
Log.d("book", book.toString());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case R.id.sax:
InputStream ins=null;
try {
ins = getAssets().open("books.xml");
SAXParser parser=new SAXParser();
List<Book> books=parser.parse(ins);
for(Book book:books){
Log.d("book", book.toString());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
default:
break;
}
}
}