XML 解析一般有三种,DOM,Pull和SAX,相比于DOM的,Pull 和SAX内存占用小效率高,所以我们一般使用Pull和SAX解析。
0:Pull和SAX都是通过工厂类来创建解析类的.
1:Pull和SAX的最大的区别就是,具体的解析的过程,SAX 是在while 循环里面通过XmlPullParser.next()来遍历的,而Pull 是通过专门的DefaultHanlder 来处理的,结构上面SAX更好,
Pull流程:
0:首先通过工厂类来获取XmlPullParser的实体类,
1:得到xml的文件的输入流,这个输入流可以是通过网络得到的也可以是通过本地得到的,例如放在raw文件夹里面的文件
2:通过setInput 来开始读取,还需要设置它的编码
//XmlPullParser的工厂类 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser = factory.newPullParser(); //xmlPullParser.setInput的第一个参数就是 InputStream, //这里是将xml 文件放在了raw文件夹里面,然后通过getResources().openRawResource(R.raw.worker)来获取 InputStream inputStream = getResources().openRawResource(R.raw.worker); //开始读取文件,并设置编码类型为utf-8 xmlPullParser.setInput(inputStream, "utf-8");
3:读取的时候是通过eventType来判断当前的位置是文件的开始开始还是结束,还是节点的开始和节点的结束.通过XmlPullParser的next的方法来跳到下一个节点。
//获取event的类型,然后循环直至END_DOCUMENT,循环的增加条件一定不能忘记eventType=xmlPullParser.next(); int eventType = xmlPullParser.getEventType(); while (eventType!=XmlPullParser.END_DOCUMENT){
.....
eventType=xmlPullParser.next();
}
4:在节点的START_TAG里面通过XmlPullParser的nextText()来获取节点里面的内容,
5:如果这个节点里面有属性,可以通过XmlPullParser的getAttributeCount来获取属性的总数,然后循环获取,通过getAttributeName getAttributeValue 来获取属性名字和值
SAX流程:
0:首先也是通过工厂类来获取SAXParser的实体类
1:然后获取XMLReader
2:创建MyHandler,
处理类DefaultHandler 里面的5个方法和我们Pull里面的while 循环里面相对应的。结构更明显。
startDocument()
startElement(String uri, String localName, String qName, Attributes attributes)
characters(char[] ch, int start, int length)
endElement(String uri, String localName, String qName)
endDocument()
记住了在endElement 里面一定要设置全局变量mQualifiedName=null,因为在xml文件里面,它会将TAB的符号也读入进来,不仅仅是节点信息,
当读完了endElement 以后,它继续读取后面的内容,例如下面的name 的节点后面就有换行符号,下一行读取到sex 之前还有两个Tab的符号。所以读取的Tab 信息会覆盖原来的Mark的这个信息
<workers>
<worker id="AQ01">
<name>Mark</name>
<sex>男</sex>
<status>经理</status>
<address>北京</address>
<money>4000</money>
</worker>
3:将MyHandler设置到xmlReader
xmlReader.setContentHandler(saxHandler);
4:然后开始读取
xmlReader.parse(new InputSource(getResources().openRawResource(R.raw.worker)));
5:最后获取List
saxList = saxHandler.getmList();
//SAX 的工厂类 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParser saxParser = saxParserFactory.newSAXParser(); // 通过parser得到XMLReader对象 XMLReader xmlReader = saxParser.getXMLReader(); //创建MyHandler的实例 MyHandler saxHandler = new MyHandler(); //将saxHanlder 放入xmlReader中。 xmlReader.setContentHandler(saxHandler); xmlReader.parse(new InputSource(getResources().openRawResource(R.raw.worker))); //此时通过MyHandler 里面的方法来获取List<Worker> saxList = saxHandler.getmList();
具体实例如下:
++++++++++++++++++++++++++++++++++++++++++++++
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>Luch</name> <sex>女</sex> <status>员工</status> <address>上海</address> <money>1000</money> </worker> <worker id="AD03"> <name>Lily</name> <sex>女</sex> <status>员工</status> <address>北京</address> <money>2000</money> </worker> <worker> <name>Lily</name> <sex>女</sex> <status>员工</status> <address>北京</address> <money>2000</money> </worker> </workers>
+++++++++++++++++++++++++++++++++++++++++++++++++++
Worker实体类
package tech.androidstudio.xmlpullparserdemo; /** * Created by Kodulf on 2016/3/18. */ public class Worker { private String id; private String name; private String sex; private String status; private String address; public Worker() { } public Worker(String id, String name, String sex, String status, String address, double money) { this.id = id; this.name = name; this.sex = sex; this.status = status; this.address = address; this.money = money; } @Override public String toString() { return "Worker{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", sex='" + sex + '\'' + ", status='" + status + '\'' + ", address='" + address + '\'' + ", money=" + money + '}'; } public double getMoney() { return money; } public void setMoney(double money) { this.money = money; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } private double money; }
++++++++++++++++++++++++++++++++++++++++++++++++++++++
MainActivity
++++++++++++++++++++++++++++++++++++++++
package tech.androidstudio.xmlpullparserdemo; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); List<Worker> list = null; try { list = pullGetList(); } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //输出结果 Log.d("kodulf", list.toString()); try { list=saxGetList(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //输出结果 Log.d("kodulf","SAX 解析的结果"+list.toString()); } private List<Worker> pullGetList() throws XmlPullParserException, IOException { /** <worker id="AQ01"> <name>Mark</name> <sex>男</sex> <status>经理</status> <address>北京</address> <money>4000</money> </worker> */ List<Worker> list = new ArrayList<Worker>(); Worker worker=null; //XmlPullParser的工厂类 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser = factory.newPullParser(); //xmlPullParser.setInput的第一个参数就是 InputStream, //这里是将xml 文件放在了raw文件夹里面,然后通过getResources().openRawResource(R.raw.worker)来获取 InputStream inputStream = getResources().openRawResource(R.raw.worker); //开始读取文件,并设置编码类型为utf-8 xmlPullParser.setInput(inputStream, "utf-8"); //获取event的类型,然后循环直至END_DOCUMENT,循环的增加条件一定不能忘记eventType=xmlPullParser.next(); int eventType = xmlPullParser.getEventType(); while (eventType!=XmlPullParser.END_DOCUMENT){ switch (eventType){ case XmlPullParser.START_DOCUMENT: Log.d("Kodulf","start document"); break; //每一个节点开始标签,开始判断,判断是哪一个节点 case XmlPullParser.START_TAG: //获取节点名字就像是name,sex,status,address,money String name = xmlPullParser.getName(); //<worker id="AQ01"> 第一个 节点,里面有一个id的属性,通过getAttribute来获取 if("worker".equals(name)){ worker = new Worker(); int attributeCount = xmlPullParser.getAttributeCount(); for (int i = 0; i < attributeCount; i++) { String attributeName = xmlPullParser.getAttributeName(i); if("id".equals(attributeName)){ String attributeValue = xmlPullParser.getAttributeValue(i); worker.setId(attributeValue); } } //节点name,获取里面的内容是通过xmlPullParser.nextText()来获取的。 }else if("name".equals(name)){ String text = xmlPullParser.nextText(); worker.setName(text); }else if("sex".equals(name)){ String text = xmlPullParser.nextText(); worker.setSex(text); }else if("status".equals(name)){ String text = xmlPullParser.nextText(); worker.setStatus(text); }else if("address".equals(name)){ String text = xmlPullParser.nextText(); worker.setAddress(text); //节点money的内容也是通过xmlPullParser.nextText()来获取, // 但是设置的时候因为我们的实体类是double类型的所以要转换一下 }else if("money".equals(name)){ String text = xmlPullParser.nextText(); worker.setMoney(Double.parseDouble(text)); } break; //在 END_TAG里面判断最后的节点,然后添加到list里面去 case XmlPullParser.END_TAG: String name1 = xmlPullParser.getName(); if ("worker".equals(name1)){ list.add(worker); } break; } //TODO 这个判断条件一定不能变 eventType=xmlPullParser.next(); } return list; } //SAX 解析 public List<Worker> saxGetList() throws ParserConfigurationException, SAXException, IOException { List<Worker> saxList = new ArrayList<Worker>(); //SAX 的工厂类 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParser saxParser = saxParserFactory.newSAXParser(); // 通过parser得到XMLReader对象 XMLReader xmlReader = saxParser.getXMLReader(); //创建MyHandler的实例 MyHandler saxHandler = new MyHandler(); //将saxHanlder 放入xmlReader中。 xmlReader.setContentHandler(saxHandler); xmlReader.parse(new InputSource(getResources().openRawResource(R.raw.worker))); //此时通过MyHandler 里面的方法来获取List<Worker> saxList = saxHandler.getmList(); return saxList; } }+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SAX的DefaultHandler
package tech.androidstudio.xmlpullparserdemo; import android.util.Log; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.util.ArrayList; import java.util.List; /** * Created by Kodulf on 2016/3/18. */ public class MyHandler extends DefaultHandler { List<Worker> mList; Worker mWorker; String mQualifiedName; /** <worker id="AQ01"> <name>Mark</name> <sex>男</sex> <status>经理</status> <address>北京</address> <money>4000</money> </worker> */ @Override public void startDocument() throws SAXException { super.startDocument(); Log.d("Kodulf", "SAX start Document"); //在 startDocument 里面初始化List mList = new ArrayList<Worker>(); } //这里的 qName-》qualified name 限定名 ,这个 参数要设置为成员变量,因为下面的characters里面需要用到。 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); mQualifiedName=qName; //如果startElement是worker的话,<worker id="AQ01">,要获取属性id的 值 if("worker".equals(qName)){ mWorker = new Worker(); int length = attributes.getLength(); for (int i = 0; i < length; i++) { String attributeName = attributes.getQName(i); if("id".equals(attributeName)){ String attributeValue = attributes.getValue(i); mWorker.setId(attributeValue); } } } } @Override public void characters(char[] ch, int start, int length) throws SAXException { /** <name>Mark</name> <sex>男</sex> <status>经理</status> <address>北京</address> <money>4000</money> */ super.characters(ch, start, length); String nodeValue = new String(ch,start,length); if("name".equals(mQualifiedName)){ mWorker.setName(nodeValue); }else if("sex".equals(mQualifiedName)){ mWorker.setSex(nodeValue); }else if("status".equals(mQualifiedName)){ mWorker.setStatus(nodeValue); }else if("address".equals(mQualifiedName)){ mWorker.setAddress(nodeValue); }else if("money".equals(mQualifiedName)){ //注意这里的Money 是double 类型的,所以要转换一下 mWorker.setMoney(Double.parseDouble(nodeValue)); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); //TODO 一定要将全局变量mQualifiedName 设置为空, //例如下面的</money>的节点后面就有换行符号,下一行读取到</worker>之前还有Tab的符号。 // 所以读取的Tab 信息会覆盖原来的4000的这个信息.所以再赋值的时候 就是将一个Tab的信息复制给Double 的了,所以报错了。 mQualifiedName=null; //判断是否是worker,如果是的话,就将mWorker 添加到list 里面去 if("worker".equals(qName)){ mList.add(mWorker); } } @Override public void endDocument() throws SAXException { super.endDocument(); Log.d("Kodulf", "SAX end Document"); } public List<Worker> getmList(){ return mList; } }