您的位置:首页 > 移动开发 > Android开发

Android Sax解析XML出现空值或脏数据的解决方案

2016-06-16 20:19 405 查看
Java解析XML一般有两种方案,一种是pull,一种是Sax解析。两种解析原理是不太一样的,但各有优势。先来说说他们的原理以及优缺点。

pull解析XML是将整块XML文件读入手机内存再进行树形解析,对于内存小的手机自然是会有卡顿的反应,而且解析的途中无法停止,倘若一个xml有几十M,效率还蛮低,但是解析出的数据信息是对称的,也就是成功率很高。

Sax(全 称 Simple API for XML)解析是将XML逐行解析,程序运行时占用内存不大,非常适合手机等嵌入式设备,但代码写起来的时候有些怪异,而且解析途中会莫名其妙出现空值或脏 数据,这让我非常苦闷,不过解决方法还是有的。还有一个优点就是可以随时停止解析,毕竟它是逐行解析。想了解更多详见Java API的org.xml.sax。

现在来说说Sax的运行机制:

//声明SAX解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//通过解析工厂类构造XMLReader对象
XMLReader reader = factory.newSAXParser().getXMLReader();
                            
//通过reander对象设置ContentHandler
reader.setContentHandler(new MyContentHandler());

//将想要解析的数据传入reader对象
reader.parse(new InputSource(new StringReader(result)));

以上是调用Sax时的核心源码,不要问为什么这么写,以现在的知识储备还无法回答,但这是官方API提供的方法,使用起来确实让人迥异万分。而 MyContentHandler 这个类需要自己重写,这个要继承DefaultHandler。
MyContentHandler详细代码:

package so.orion.XMLSax;

import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

public class MyContentHandler extends DefaultHandler {

String name = "", sex = "", age = "", address = "";

String tagName ;

String temp ="" ;

@Override

public void characters(char[] ch, int start, int length) throws SAXException {

//System.out.println("Test—>" + this.tagName + "—" +  new String (ch , start , length) );

String sb = new String(ch, start, length);

temp = temp + sb;

}

@Override

public void endDocument() throws SAXException {

System.out.println("…………..end…………..");

}

@Override

public void endElement(String uri, String localName, String qName)

throws SAXException {

if( localName.equals( "student" )){

this.printAll();

}

if( tagName.equals("name")){

this.name = temp;

}else if( tagName.equals("sex")){

this.sex = temp;

}else if( tagName.equals("age")){

this.age = temp;

}else if( tagName.equals("address")){

this.address = temp;

}

}

@Override

public void startDocument() throws SAXException {

System.out.println("…………..begin…………..");

}

@Override

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

this.tagName = localName ;

this.temp = "";

if( tagName.equals("student") ){

System.out.println("————————————–");

forint i = 0 ; i<attributes.getLength() ; i++ ){

System.out.println( attributes.getLocalName(i) + " : "+attributes.getValue(i) );

}

}

}

public void printAll( ){

System.out.println("Name : " + this.name);

System.out.println("Sex : " + this.sex);

System.out.println("Age : " + this.age);

System.out.println("Address : " + this.address);

}

}
网上提供的简单解析过程是:startDocument->startElement->characters->endElement->endDocument

清晰点的详解图应该是:



解析器没有解析完标签时会在 startElement 和 endElement之间循环,但是我实验得出的结论是:



startDocument之后还会执行一次characters,而不知何种原因数据量非常非常小的时候characters也会自动解析多次。
说说我遇到的问题,源数据如下:
<?xml version="1.0" encoding="utf-8"?>
<students>
    <student id="1240">
        <name>Tony</name>
        <sex>boy</sex>
        <age>22</age>
        <address>G301</address>
    </student>
    <student id="1241">
        <name>John</name>
        <sex>boy</sex>
        <age>21</age>
        <address>G302</address>
    </student>
    <student id="1243">
        <name>Sally</name>
        <sex>girl</sex>
        <age>21</age>
        <address>T2132</address>
    </student>
    <student id="1244">
        <name>Tom</name>
        <sex>boy</sex>
        <age>23</age>
        <address>G303</address>
    </student>
</students>

解析时出现空数据:



网上的大神在数据处理时将成员变量在characters中做赋值判断处理,而我仿照时出现的问题怪异,于是小弟将判断处理这个代码写在 endElement里,每次标签结束后再对当前成员变量进行赋值操作,而characters无论执行多少次,我只要在成员变量声明一个String temp,在characters中执行String sb = new String(ch,start,length); temp = temp + sb ;  ,在下一个startElement开始的时候再将temp赋值为空就可以了。无论中间如何执行数据都不会丢失或出现脏数据的情况,即使遇到换行符也是一样可以多次执行。

修改后的代码执行后结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: