Android笔记之xml(SAX)解析

Android的xml SAX解析的原理是逐行解析,然后调用相应的函数。

ContentHandler接口中主要用到的函数有:

  • 解析文档开始 startDocument()
  • 解析文档结束 endDocument()
  • 解析标签开始 startElement(String uri, String localName, String qName, Attributes atts)
  • 解析标签结束 endElement(Stringuri, StringlocalName, String qName)
  • 解析标签内容 characters(char[] ch, int start, int length)
由于实现接口必须重写所有方法,所以我们选择继承DefaultHandler这个类,DefaultHandler是对ContentHandler接口中所有方法
的空实现,就是所谓的适配器模式。

首先先看一下我们要解析的testxml.xml
<?xml version="1.0" encoding="UTF-8"?>
<workers>
	<worker id="AQ01">
		<name>Mark</name>
		<sex>男</sex>
		<status>经理</status>
		<address>北京</address>
		<money>4000</money>
	</worker>
	<worker id="AD02">
		<name>lucy</name>
		<sex>女</sex>
		<status>员工</status>
		<address>上海</address>
		<money>1000</money>
	</worker>
	<worker id="AD03">
		<name>lily</name>
		<sex>女</sex>
		<status>员工</status>
		<address>北京</address>
		<money>3000</money>
	</worker>
</workers>

我把testxml.xml放在res/raw/testxml.xml,raw文件夹需要自己建。
(不要放在xml目录,因为我只是以字符串的方式读入)
//读取res/raw/testxml.xml并转换成字符串
InputStream inputStream = getResources().openRawResource(R.raw.testxml);
String resultStr = getString(inputStream);
System.out.println(resultStr); 
这个方法是将输入的InputStream转化成字符串,网上看到的http://blog.csdn.net/barryhappy/article/details/7365271
其中 inputStreamReader = new InputStreamReader(inputStream, "utf-8");"utf-8"要用自己xml文件的编码
/**
 * 输入一个inputStream返回字符串
 */
public static String getString(InputStream inputStream) {
    InputStreamReader inputStreamReader = null;
    try {
        inputStreamReader = new InputStreamReader(inputStream, "utf-8");
    } catch (UnsupportedEncodingException e1) {
        e1.printStackTrace();
    }
    BufferedReader reader = new BufferedReader(inputStreamReader);
    StringBuffer sb = new StringBuffer("");
    String line;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line);
            sb.append("\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return sb.toString();
}
主Activity的完整代码XMLActivity.java,getString()方法懒得封装了,就直接丢进主代码里面
package com.example.xml;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;

import javax.xml.parsers.SAXParserFactory;

public class XMLActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //读取res/raw/.xml并转换成字符串
        InputStream inputStream = getResources().openRawResource(R.raw.testxml);
        String resultStr = getString(inputStream);
        System.out.println(resultStr);
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            XMLReader reader = factory.newSAXParser().getXMLReader();
            reader.setContentHandler(new MyContentHandler());
            reader.parse(new InputSource(new StringReader(resultStr)));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 输入一个inputStream返回字符串
     */
    public static String getString(InputStream inputStream) {
        InputStreamReader inputStreamReader = null;
        try {
            inputStreamReader = new InputStreamReader(inputStream, "utf-8");
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }
        BufferedReader reader = new BufferedReader(inputStreamReader);
        StringBuffer sb = new StringBuffer("");
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
}


下面是看mars的视频教学打的MyContentHandler.java

package com.example.xml;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MyContentHandler extends DefaultHandler {
    String hisname, address, money, sex, status;
    String tagName;
    int i=0;
    boolean flag;
    @Override
    public void startDocument() throws SAXException {
        System.out.println("``````````begin``````````");
    }

    @Override
    public void endDocument() throws SAXException {
        System.out.println("``````````end``````````");
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        flag = true;
        tagName = localName;
        if(localName.equals("worker")) {
            for(int i=0; i<attributes.getLength(); i++) {
                System.out.println(attributes.getLocalName(i) + "=" + attributes.getValue(i));
            }
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        flag = false;
        if(localName.equals("worker")) {
            this.printout();
        }
    }

    private void printout() {
        System.out.print("name: ");
        System.out.println(hisname);
        System.out.print("sex: ");
        System.out.println(sex);
        System.out.print("status: ");
        System.out.println(status);
        System.out.print("address: ");
        System.out.println(address);
        System.out.print("money: ");
        System.out.println(money);
        System.out.println();
    }

    /**
     * characters并不是只执行一次,只有在startElement和endElement之间的那一次才是正确的
     * 所以设置一个flag
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        //System.out.println(i++);
        if(flag) {
            if (tagName.equals("name"))
                hisname = new String(ch, start, length);
            else if (tagName.equals("sex"))
                sex = new String(ch, start, length);
            else if (tagName.equals("status"))
                status = new String(ch, start, length);
            else if (tagName.equals("address"))
                address = new String(ch, start, length);
            else if (tagName.equals("money"))
                money = new String(ch, start, length);
        }
    }
}
这里主要是 characters()这个方法并不是在解析每个标签中只执行一次,是个坑,

在一个标签解析结束执行endElement后,和在下一个标签解析开始之前,如果碰到"\t"、"\n"之类的characters()也会执行,

视频教学并没有提到。

找了好久才找到一片文章提到这个问题,原文http://blog.csdn.net/feng88724/article/details/7013675

我的解决方法是,既然在startElement和endElement之间执行的characters()获取的数据才是正确的,

那么设个flag,来控制characters()往变量赋值。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值