您好,登錄后才能下訂單哦!
小編給大家分享一下XML文件解析SAX/DOM/PULL的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
Sax特點( SAX是Simple API for XML的簡稱)
1. 解析效率高,占用內存少
2.可以隨時停止解析
3.不能載入整個文檔到內存
4.不能寫入xml
5.SAX解析xml文件采用的是事件驅動
pull與sax的不同之處
1.pull讀取xml文件后觸發相應的事件調用方法返回的是數字。
2.pull可以在程序中控制,想解析到哪里就可以停止到哪里
3.Android中更推薦使用pull解析
DOM的特點
優點
1.整個文檔樹在內存中,便于操作;支持刪除、修改、重新排列等多種功能
2.通過樹形結構存取xml文檔
3.可以在樹的某個節點上向前或向后移動
缺點
1.將整個文檔調入內存(包括無用的節點),浪費時間和空間
適用場合
一旦解析了文檔還需多次訪問這些數據;硬件資源充足(內存,cpu)
首先定義我定義了一個Student.xml文件
**示例**
[code]<?xml version="1.0" encoding="utf-8"?> <students> <student id="1" > <name> 小紅 </name> <age> 21 </age> <sex> 女 </sex> <adress> 上海 </adress> </student> <student id="2" > <name> 小黑 </name> <age> 22 </age> <sex> 男 </sex> <adress> 天津 </adress> </student> <student id="3" > <name> 小網 </name> <age> 23 </age> <sex> 男 </sex> <adress> 北京 </adress> </student> </students>
**1.sax解析**
[code]package com.example.sax_xml; import java.io.IOException; import java.io.InputStream; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import android.app.Activity; import android.content.res.AssetManager; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void sax_xml(View v) { // 得到設備管理者對象 AssetManager manager = this.getAssets(); try { // 獲取到assets目錄下的Student.xml文件輸入流 InputStream is = manager.open("Student.xml"); /** * SAXParserFactory 定義了一個API工廠,使得應用程序可以配置和獲得一個基于SAX(Simple API for * XML * * )的解析器,從而能夠解析XML文檔( 原文: Defines a factory API that enables * applications to configure and obtain a SAX based parser to parse * XML documents. ) * * 它的構造器是受保護的,因而只能用newInstance()方法獲得實例( Protected constructor to * force use of newInstance(). ) */ SAXParserFactory factory = SAXParserFactory.newInstance(); /** * XmlReader 類是一個提供對 XML 數據的非緩存、只進只讀訪問的抽象基類。 該類符合 W3C 可擴展標記語言 (XML) * 1.0 和 XML 中的命名空間的建議。 XmlReader 類支持從流或文件讀取 XML 數據。 * 該類定義的方法和屬性使您可以瀏覽數據并讀取節點的內容。 當前節點指讀取器所處的節點。 * 使用任何返回當前節點值的讀取方法和屬性推進讀取器。 XmlReader 類使您可以: 1. 檢查字符是不是合法的 * XML字符,元素和屬性的名稱是不是有效的 XML 名稱。 2. 檢查 XML 文檔的格式是否正確。 3. 根據 DTD * 或架構驗證數據。 4.從 XML流檢索數據或使用提取模型跳過不需要的記錄。 */ XMLReader xmlReader = factory.newSAXParser().getXMLReader(); /** * ContentHandler是Java類包中一個特殊的SAX接口,位于org.xml.sax包中。該接口封裝了一些對事件處理的方法 * ,當XML解析器開始解析XML輸入文檔時,它會遇到某些特殊的事件,比如文檔的開頭和結束、元素開頭和結束、以及元素中的字符數據等事件 * 。當遇到這些事件時,XML解析器會調用ContentHandler接口中相應的方法來響應該事件。 */ //由于它是一個接口所以我直接編寫一個類繼承它的子類DefaultHandler,重新其方法 ContentHandler handler = new ContentHandler(); // 將ContentHandler的實例設置到XMLReader中 // setContentHandler此方法設置 XML 讀取器的內容處理程序 xmlReader.setContentHandler(handler); // 開始執行解析 //InputSource:XML 實體的單一輸入源。 xmlReader.parse(new InputSource(is)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
**自己定義的ContentHandler類**
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import android.util.Log; public class ContentHandler extends DefaultHandler { private StringBuilder id; private StringBuilder name; private StringBuilder sex; private StringBuilder age; private StringBuilder adress; private String nodeName;// 記錄當前節點的名字 // 開始xml解析的時候調用 @Override public void startDocument() throws SAXException { id = new StringBuilder(); name = new StringBuilder(); sex = new StringBuilder(); age = new StringBuilder(); adress = new StringBuilder(); } // 開始解析某個節點的時候調用 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { nodeName = localName; } // 獲取某個節點中的內容時調用 @Override public void characters(char[] ch, int start, int length) throws SAXException { if ("id".equals(nodeName)) { id.append(ch, start, length); } else if ("name".equals(nodeName)) { name.append(ch, start, length); } else if ("age".equals(nodeName)) { age.append(ch, start, length); } else if ("sex".equals(nodeName)) { sex.append(ch, start, length); } else if ("adress".equals(nodeName)) { adress.append(ch, start, length); } } //完成某個節點的解析的時候調用 @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("student".equals(localName)) { Log.d("ContentHandler", "id is" + id.toString().trim()); Log.d("ContentHandler", "name is" + name.toString().trim()); Log.d("ContentHandler", "age is" + age.toString().trim()); Log.d("ContentHandler", "sex is" + sex.toString().trim()); Log.d("ContentHandler", "adress is" + adress.toString().trim()); // 最后要將StringBuilder清空掉 id.setLength(0); name.setLength(0); age.setLength(0); sex.setLength(0); adress.setLength(0); } } //完成整個XML解析的時候調用 @Override public void endDocument() throws SAXException { // TODO Auto-generated method stub super.endDocument(); } }
**2.pull解析**
[code]package com.example.xmlpull; import android.app.Activity; import android.content.res.AssetManager; import android.os.Bundle; import android.util.Log; import android.util.Xml; import android.view.View; import android.widget.Toast; import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * * 讀取到xml的聲明返回數字0 START_DOCUMENT; * 讀取到xml的結束返回數字1 END_DOCUMENT ; * 讀取到xml的開始標簽返回數字2 START_TAG * 讀取到xml的結束標簽返回數字3 END_TAG * 讀取到xml的文本返回數字4 TEXT * */ public class MainActivity extends Activity { /** * 用于裝載解析出來的數據 */ private List<Map<String, Object>> oList; private Map<String, Object> oMap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void btn_pull(View v) { // 獲取設備管理器對象 AssetManager manager = this.getAssets(); try { // 得到assets文件下的Student.xml文件輸入流 InputStream is = manager.open("Student.xml"); // 得到pull解析對象,它的構造器是受保護的,因而只能用newInstance()方法獲得實例 XmlPullParser parser = Xml.newPullParser(); // 將xml文件輸入流傳給pull解析對象 parser.setInput(is, "UTF-8"); // 獲取解析時的事件類型, int type = parser.getEventType(); // 使用while循環,如果解析的事件類型不等于全文檔最后節點類型,一直解析 while (type != XmlPullParser.END_DOCUMENT) { // 得到當前的節點名字 String nodeName = parser.getName(); switch (type) { // 如果是全文檔的開始節點類型 case XmlPullParser.START_DOCUMENT: // 初始化裝載數據的集合 oList = new ArrayList<Map<String, Object>>(); break; // 如果是group開始節點類型 case XmlPullParser.START_TAG: // 根據解析的節點名字進行判斷 if ("students".equals(nodeName)) { } else if ("student".equals(nodeName)) { oMap = new HashMap<String, Object>(); // 得到group開頭的student節點 String id = parser.getAttributeValue(0); oMap.put("id", id); } else if ("name".equals(nodeName)) { // 節點對應的文本 String name = parser.nextText(); oMap.put("name", name); } else if ("sex".equals(nodeName)) { String sex = parser.nextText(); oMap.put("sex", sex); } else if ("age".equals(nodeName)) { String age = parser.nextText(); oMap.put("age", age); } else if ("adress".equals(nodeName)) { String adress = parser.nextText(); oMap.put("adress", adress); } break; // 到了group最后的節點 case XmlPullParser.END_TAG: if ("name".equals(nodeName)) { Toast.makeText(this, "姓名解析完成", Toast.LENGTH_LONG) .show(); } if ("student".equals(nodeName)) { oList.add(oMap); } break; } //切換到下一個group type = parser.next(); } } catch (Exception e) { e.printStackTrace(); } //最后遍歷集合Log for (int i = 0; i < oList.size(); i++) { Log.e("error", "name:" + oList.get(i).get("name") + "----sex:" + oList.get(i).get("sex") + "----age:" + oList.get(i).get("age") + "----address:" + oList.get(i).get("adress")); } } }
首先說一下DOM解析需要注意的地方,因為講這個的時候我們老師就犯了這個錯誤,這里特別指出一下
在這里當我們得到節點student時,也就是圖中箭頭所畫的地方,如果我們調用它的getChildNodes()方法,大家猜猜它的子節點有幾個?不包括它的孫子節點,小紅這種的除外,因為它是孫子節點。它總共有5個子節點,分別是圖中黑色橫線標記的那樣。所以在解析時,一定要小心,不要忽略空白的地方。
下面附上具體解析代碼
這里我是把dom解析的部分拆分成了一個工具類
[code]package com.example.domxml; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** *Dom解析是將xml文件全部載入,組裝成一顆dom樹, *然后通過節點以及節點之間的關系來解析xml文件,一層一層撥開 */ public class Dom_xml_Util { private List<Student> list = new ArrayList<Student>(); public List<Student> getStudents(InputStream in) throws Exception{ //獲取dom解析工廠,它的構造器是受保護的,因而只能用newInstance()方法獲得實例 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //使用當前配置的參數創建一個新的 DocumentBuilder 實例 //DocumentBuilder使其從 XML 文檔獲取 DOM 文檔實例。 //使用此類,應用程序員可以從 XML 獲取一個 Document DocumentBuilder builder = factory.newDocumentBuilder(); //獲取Document Document document = builder.parse(in); //getDocumentElement()這是一種便捷屬性,該屬性允許直接訪問文檔的文檔元素的子節點 //Element 接口表示 HTML 或 XML 文檔中的一個元素 Element element = document.getDocumentElement(); //以文檔順序返回具有給定標記名稱的所有后代 Elements 的 NodeList NodeList bookNodes = element.getElementsByTagName("student"); //遍歷NodeList //getLength()列表中的節點數 for(int i=0;i<bookNodes.getLength();i++){ //返回集合中的第 i個項 Element bookElement = (Element) bookNodes.item(i); Student student = new Student(); //得到item大節點中的屬性值。 student.setId(Integer.parseInt(bookElement.getAttribute("id"))); //得到大節點中的小節點的Nodelist NodeList childNodes = bookElement.getChildNodes(); // System.out.println("*****"+childNodes.getLength()); //遍歷小節點 for(int j=0;j<childNodes.getLength();j++){ /** * getNodeType()表示基礎對象的類型的節點 * Node.ELEMENT_NODE 該節點為 Element * getNodeName()此節點的名稱,取決于其類型 * getFirstChild() 此節點的第一個子節點 * getNodeValue()此節點的值,取決于其類型 */ if(childNodes.item(j).getNodeType()==Node.ELEMENT_NODE){ if("name".equals(childNodes.item(j).getNodeName())){ student.setName(childNodes.item(j).getFirstChild().getNodeValue()); }else if("age".equals(childNodes.item(j).getNodeName())){ student.setAge(Integer.parseInt(childNodes.item(j).getFirstChild().getNodeValue())); }else if("sex".equals(childNodes.item(j).getNodeName())){ student.setSex(childNodes.item(j).getFirstChild().getNodeValue()); }else if("address".equals(childNodes.item(j).getNodeName())){ student.setAddress(childNodes.item(j).getFirstChild().getNodeValue()); } } }//end for j list.add(student); }//end for i return list; } }
Student.class
[code]package com.example.domxml; public class Student { private int id; private String name; private int age; private String sex; private String address; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
在activity中調用
activity_main
[code]<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/tv_id" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_name" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_age" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_sex" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_adress" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
MainActivity
[code]package com.example.domxml; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import android.os.Bundle; import android.app.Activity; import android.content.res.AssetManager; import android.view.Menu; import android.view.View; import android.widget.TextView; public class MainActivity extends Activity { private TextView tv_id,tv_name,tv_age,tv_sex,tv_adress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_id=(TextView)findViewById(R.id.tv_id); tv_name=(TextView)findViewById(R.id.tv_name); tv_age=(TextView)findViewById(R.id.tv_age); tv_sex=(TextView)findViewById(R.id.tv_sex); tv_adress=(TextView)findViewById(R.id.tv_adress); } public void bnt_parse(View v) { AssetManager manager=getAssets(); try { InputStream in=manager.open("Student.xml"); List<Student> oList =new ArrayList<Student>(); try { //返回一個泛型為Student的集合 oList = new Dom_xml_Util().getStudents(in); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } //遍歷集合,取集合中的第一組數據 for (int i = 0; i < oList.size(); i++) { tv_id.setText(oList.get(0).getId()); tv_name.setText(oList.get(0).getName()); tv_age.setText(oList.get(0).getAge()); tv_sex.setText(oList.get(0).getSex()); tv_adress.setText(oList.get(0).getAddress()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
以上是“XML文件解析SAX/DOM/PULL的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。