1. 程式人生 > >Android Studio 解析XML的三種方法

Android Studio 解析XML的三種方法

一丶概述

檔案解析要求,json解析和xml解析,前面文章說過Json轉實體類,這裡就說說解析XML

內容:

Android Studio 解析XML常見的三種方式:DOM PULL SAX (實現XML轉實體類並列印輸出)

效果演示:


二丶正文

SAX(Simple API for XML) 使用流式處理的方式,它並不記錄所讀內容的相關資訊。它是一種以事件為驅動的XML API,解析速度快,佔用記憶體少。使用回撥函式來實現。 缺點是不能倒退。

DOM(Document Object Model) 是一種用於XML文件的物件模型,可用於直接訪問XML文件的各個部分。它是一次性全部將內容載入在記憶體中,生成一個樹狀結構,它沒有涉及回撥和複雜的狀態管理。 缺點是載入大文件時效率低下。

Pull內置於Android系統中。也是官方解析佈局檔案所使用的方式。Pull與SAX有點類似,都提供了類似的事件,如開始元素和結束元素。不同的是,SAX的事件驅動是回撥相應方法,需要提供回撥的方法,而後在SAX內部自動呼叫相應的方法。而Pull解析器並沒有強制要求提供觸發的方法。因為他觸發的事件不是一個方法,而是一個數字。它使用方便,效率高。

SAX、DOM、Pull的比較: 
1. 記憶體佔用:SAX、Pull比DOM要好; 
2. 程式設計方式:SAX採用事件驅動,在相應事件觸發的時候,會呼叫使用者編好的方法,也即每解析一類XML,就要編寫一個新的適合該類XML的處理類。DOM是W3C的規範,Pull簡潔。 
3. 訪問與修改:SAX採用流式解析,DOM隨機訪問。 
4. 訪問方式:SAX,Pull解析的方式是同步的,DOM逐字逐句

這裡不做詳細講解,看註釋,上程式碼


XML

<?xml version="1.0" encoding="UTF-8" ?>
<persons>
    <person id="23">
        <name>李雷</name>
        <age>30</age>
    </person>
    <person id="20">
        <name>韓梅梅</name>
        <age>25</age>
    </person>
</persons>
person.Java
public class Person {
    Integer id;
String name;
Short age;
    public Integer getId() {
        return id;
}

    public void setId(Integer id) {
        this.id = id;
}

    public String getName() {
        return name;
}

    public void setName(String name) {
        this.name = name;
}

    public Short getAge() {
        return age;
}

    public void setAge(Short age) {
        this.age = age;
}

    @Override
public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
}
}
XMLtoEntityActivity
public class XMLtoEntityActivity extends AppCompatActivity {
    private TextView tv_show_entity;
    private String string = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.xmlto_entity_activity);
tv_show_entity = (TextView) findViewById(R.id.tv_show_entity);
}

    public void startXML(View view){
//        SAXService saxService = new SAXService();
//        DOMService domService = new DOMService();
PULLService pullService = new PULLService();
        try {
            InputStream inputStream = getAssets().open("Users.xml");
//            List<Person> persons = saxService.getPerson(inputStream);
//            List<Person> persons = domService.getPersons(inputStream);
List<Person> persons = pullService.getPersons(inputStream);
            for (Person person : persons) {
                Log.e("TAG",person.toString());
string += person.toString();
}
        } catch (IOException e) {
            e.printStackTrace();
} catch (Exception e) {
            e.printStackTrace();
}
        tv_show_entity.setText(string);
}
}
DOM方法
/**
 * 採用DOM解析XML內容
 */
public class DOMService {
    public List<Person> getPersons(InputStream inputStream) throws Exception {

        List<Person> persons = new ArrayList<>();
//獲取DOM解析器工廠
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//獲DOM解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//將解析樹放入記憶體,通過返回值Document來描述結果
Document document = builder.parse(inputStream);
//取得根元素<personos>
Element root = document.getDocumentElement();
//取得所有person節點集合
NodeList personNodes = root.getElementsByTagName("person");
        for (int i = 0; i < personNodes.getLength(); i++) {
            Person person = new Person();
//取得person節點元素
Element personElement = (Element) personNodes.item(i);
//取得屬性值並設定ID
person.setId(Integer.parseInt(personElement.getAttribute("id")));
//獲取person的子節點
NodeList personChilds = personElement.getChildNodes();
            for (int j = 0; j < personChilds.getLength(); j++) {
                //判斷當前節點是否是元素型別的節點
if (personChilds.item(j).getNodeType() == Node.ELEMENT_NODE) {
                    Element childElement = (Element) personChilds.item(j);
                    if ("name".equals(childElement.getNodeName())) {
                        //獲取孫節點的值
person.setName(childElement.getFirstChild().getNodeValue());
} else if ("age".equals(childElement.getNodeName())) {
                        person.setAge(Short.parseShort(childElement.getFirstChild().getNodeValue()));
}
                }
            }
            persons.add(person);
}
        return persons;
}
}
PULL方法
/**
 * 採用PULL解析XML內容
 */
public class PULLService {
    public List<Person> getPersons(InputStream inputStream) throws Exception {
        List<Person> persons = null;
Person person = null;
//得到PULL解析器
XmlPullParser parser = Xml.newPullParser();
parser.setInput(inputStream,"UTF-8");
//產生事件
int eventType = parser.getEventType();
//如果不是文件結束事件就迴圈推進
while (eventType != XmlPullParser.END_DOCUMENT) {
            switch (eventType) {
                case XmlPullParser.START_DOCUMENT://開始文件事件
persons = new ArrayList<>();
                    break;
                case XmlPullParser.START_TAG://開始元素事件
                    //獲取解析器當前指向的元素的名稱
String name = parser.getName();
                    if ("person".equals(name)) {
                        person = new Person();
person.setId(Integer.parseInt(parser.getAttributeValue(0)));
}
                    if (person != null) {
                        if ("name".equals(name)) {
                            //獲取解析器當前指向元素的下一個文字節點的值
person.setName(parser.nextText());
}
                        if ("age".equals(name)) {
                            person.setAge(Short.parseShort(parser.nextText()));
}
                    }
                    break;
                case XmlPullParser.END_TAG://結束元素事件
                    //判斷是都是person的結束事件
if ("person".equals(parser.getName())) {
                        persons.add(person);
person = null;
}
                    break;
}
            //進入下一個元素並觸發相應的事件
eventType = parser.next();
}
        return persons;
}
}
SAX方法
/**
 * 採用SAX解析XML內容
 */
public class SAXService {
    public List<Person> getPerson(InputStream inputStream) throws Exception {
        //得到SAX解析工廠
SAXParserFactory factory = SAXParserFactory.newInstance();
//得到SAX解析器
SAXParser parser = factory.newSAXParser();
PersonParser personParser = new PersonParser();
parser.parse(inputStream,personParser);
inputStream.close();
        return personParser.getPersons();
}
    private final class PersonParser extends DefaultHandler {

        private List<Person> persons = null;
        private String tag = null;//記錄當前解析到了那個元素節點名稱
private Person person;
        public List<Person> getPersons(){
            return persons;
}
        //一開始會執行這個方法,所以在這裡面完成初始化
@Override
public void startDocument() throws SAXException {
            persons = new ArrayList<>();
}

        @Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            //判斷元素節點是否等於person
if ("person".equals(localName)) {
                person = new Person();
//獲取資料,引數為索引下標
person.setId(Integer.parseInt(attributes.getValue(0)));
}
            tag = localName;
}

        @Override
public void endElement(String uri, String localName, String qName) throws SAXException {
            if ("person".equals(localName)) {
                persons.add(person);
person = null;
}
            tag = null;
}

        @Override
public void characters(char[] ch, int start, int length) throws SAXException {
            if (tag != null) {
                //獲取文字節點的資料
String data = new String(ch, start, length);
                if ("name".equals(tag)) {
                    person.setName(data);
} else if ("age".equals(tag)) {
                    person.setAge(Short.parseShort(data));
}
            }
        }
    }
}

總結:Android開發主流是傳json,而XML解析一般跟網路請求,爬蟲資料相關。當然兩者也是可以相互轉換的,Java只強大在於提供了很多的類和方法。只要你願意學,方法總是有的