在Android系统中,对于XML文件的读取主要采用的是SAX方法。SAX是一个用于处理XML事件驱动的“推”模型,虽然它不是W3C标准,但它却是一个得到了广泛认可的API。SAX解析器不像DOM那样建立一个完整的文档树,而是在读取文档时激活一系列事件,这些事件被推给事件处理器,然后由事件处理器提供对文档内容的访问。
常见的事件处理器有三种基本类型:
a. 用于访问XML DTD内容的DTDHandler;
b. 用于低级访问解析错误的ErrorHandler;
c. 用于访问文档内容的ContentHandler,这也是最普遍使用的事件处理器。
因为SAX具有边扫描边读取的特性,无需将整个文件读入内存中,更好的节省了移动设备中的资源。但是这种方法对于操作节点显得略有复杂。
下面以本人在学习中所看过的一个视频教程中的实例,说明Android应用程序对于XML文档的解析过程。
用于开启解析的Activity:
- public class XMLActitity extends Activity {
-
- private Button parseButton ;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- parseButton = (Button)findViewById(R.id.parseButton);
- parseButton.setOnClickListener(new ParseButtonListener());
- }
- //设定监听器,当点击按钮时,开始进行解析。
- class ParseButtonListener implements OnClickListener{
-
- @Override
- public void onClick(View v) {
- HttpDownloader hd = new HttpDownloader();
- //将网络上的一个XML资源下载并解析成为一个字符串,这里的解析在一个外部类中进行,这里不再列出。
- String resultStr = hd.download("http://192.168.1.107:8081/voa1500/test.xml");
- System.out.println(resultStr);
- try{
- //下面是解析XML的
-
- SAXParserFactory factory = SAXParserFactory.newInstance(); //2
- XMLReader reader = factory.newSAXParser().getXMLReader();
-
- reader.setContentHandler(new MyContentHandler());
-
- reader.parse(new InputSource(new StringReader(resultStr)));
-
- }
- catch(Exception e){
- e.printStackTrace();
- }
- }
-
- }
- }
|
内容处理器:
SAX时间作为驱动的解析模型,需要相应的事件处理函数。SAX将不同的事件处理函数按照类型分不同接口中。对于文件内容的处理函数,在内容处理器接口(ContentHandler)中。
- public class MyContentHandler extends DefaultHandler {
- String hisname, address, money, sex, status;
- String tagName;
-
- //当开始解析文档时,触发这个函数
- public void startDocument() throws SAXException {
- System.out.println("````````begin````````");
- }
- //当结束解析文档时,触发这个函数
- public void endDocument() throws SAXException {
- System.out.println("````````end````````");
- }
- //当扫描到开始标签时,触发这个函数。
- public void startElement(String namespaceURI, String localName,
- String qName, Attributes attr) throws SAXException {
- //使用全局变量tagName作为当前正在解析节点的标记。
- tagName = localName;
- if (localName.equals("worker")) {
-
- for (int i = 0; i < attr.getLength(); i++) {
- //打印其中某个属性的名称和属性值
- System.out.println(attr.getLocalName(i) + "=" + attr.getValue(i));
- }
- }
- }
-
- public void endElement(String namespaceURI, String localName, String qName)
- throws SAXException {
-
- tagName = "";
- if (localName.equals("worker")) {
- this.printout();
- }
- }
- //当扫描到标签内容时,触发这个函数。标签的内容存储在字符数组中。
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- //首先判断当前扫描到的标签,然后根据当前标签判断标签内容
- 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);
- }
-
- 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();
- }
-
- }
|
在上面程序中,需要注意,我们并非实现了ContentHandler接口,而是继承了已经实现该接口的DefaultHandler。我再付类中已经实现了接口中所有方法,并将方法实现为空方法,我们继承父类只需要重写那些我们需要的方法即可。