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>person.Java</persons>
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只強大在於提供了很多的類和方法。只要你願意學,方法總是有的