4--安卓網路程式設計之XML總彙篇
零、前言
Xml是一種應用廣泛的標記語言,我們常見的html便是它的子集。形如:<XXX>xxx</XXX>組成的閉合標籤
安卓的res目錄下的xml想必大家都是否熟悉,它們最終都是在程式碼中被讀取並解析發揮效果的
安卓的SharedPreferences是以Xml的形式儲存資料的,就連AndroidManifest注意一看也是Xml
可以說xml涉及到了安卓的很多方面,我們並不陌生,Xml最大的好處就是解耦,容易複用和更換

pull解析.png
XML常見的三種解析方式:
解析方式 | 載入驅動方式 | 可修改? | 自定義結束? | 效率 | 備註 |
---|---|---|---|---|---|
Pull解析 | 事件驅動 | 否 | 是 | 高 | 安卓專有 |
Sax解析 | 事件驅動 | 否 | 否 | 高 | 無 |
Dom解析 | 直接全部載入 | 是 | 否 | 低 | 解析時構建dom樹 |
準備的待解析xml:
<?xml version="1.0" encoding="UTF-8"?> <weapons> <weapon material="玉" type="劍"> <name>問天劍</name> <atk>2000</atk> <user>語熙華</user> </weapon> <weapon material="鐵" type="刀"> <name>皇刀</name> <atk>3000</atk> <user>九方玄玉</user> </weapon> </weapons>
一、Pull解析概述
Pull是安卓內建的,基於事件觸發的解析器 Pull解析器小巧輕便,解析速度快,簡單易用 主動從解析器中獲取事件,可以在滿足了需要的條件後不再獲取事件,結束解析
1、Pull解析Xml:
private ArrayList<WeaponXml> parseXmlWithPull() { InputStream is = null; try { //XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); //XmlPullParser pullParser = factory.newPullParser(); //獲得Xml解析器--等價上兩句 XmlPullParser pullParser = Xml.newPullParser(); //得到一個含有xml的is輸入流 is = getAssets().open("weapon.xml"); //設定輸入流 pullParser.setInput(is, "utf-8"); //觸發第一個事件:eventType=0 即:START_DOCUMENT int eventType = pullParser.getEventType(); //沒有讀到文件結束之前都在while裡走 while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) {//根據事件型別執行 case XmlPullParser.START_DOCUMENT://文件開始 //新建物件的集合 mWeapons = new ArrayList<>(); break; case XmlPullParser.START_TAG://讀到第一個標籤時再進行switch選擇 switch (pullParser.getName()) {//拿到標籤名稱 case "weapon"://如果標籤是weapon //新建一個 Weapon物件用來記錄資訊 mWeapon = new WeaponXml(); //獲取第一個屬性值 String material = pullParser.getAttributeValue(0); //獲取第二個屬性值 String type = pullParser.getAttributeValue(1); //物件裝載得到的屬性 mWeapon.setType(type); mWeapon.setMaterial(material); break; case "name": //對於沒有屬性的標籤,可以用nextText獲取標籤內部的文字 String name = pullParser.nextText(); mWeapon.setName(name); break; case "atk": Short atk = new Short(pullParser.nextText()); mWeapon.setAtk(atk); break; case "user": String user = pullParser.nextText(); mWeapon.setUser(user); break; } break; case XmlPullParser.END_TAG://當事件型別是終止標籤時:即</XXX> if ("weapon".equals(pullParser.getName())) { mWeapons.add(mWeapon);//將生成物件加入集合,一個 } break; } eventType = pullParser.next();//解析下一元素,更新event } } catch (Exception e) { e.printStackTrace(); }finally { if (is != null) { try { is.close();//關流 } catch (IOException e) { e.printStackTrace(); } } } return mWeapons; }
2、Pull寫入Xml:
/** * 備份Xml--當然也可以備份任意的實體類作為Xml,比如簡訊,聯絡人 */ private void backUpXml() { ArrayList<WeaponXml> weapons = parseXmlWithPull(); XmlSerializer serializer = Xml.newSerializer(); FileOutputStream fos = null; try { String path = Environment.getExternalStorageDirectory().getAbsolutePath(); fos = new FileOutputStream(path + File.separator + "weapon.xml"); serializer.setOutput(fos, "utf-8"); //文件開始 serializer.startDocument("utf-8", true); serializer.startTag("", "weapons"); for (WeaponXml weapon : weapons) { //新建標籤: <weapon> serializer.startTag(null, "weapon"); //設定屬性: material="玉" type="劍" serializer.attribute("","material", weapon.getMaterial()); serializer.attribute("","type", weapon.getType()); //巢狀子標籤:<name>問天劍</name> serializer.startTag(null, "name"); serializer.text(weapon.getName().trim()); serializer.endTag(null, "name"); serializer.startTag(null, "atk"); serializer.text(weapon.getAtk() + ""); serializer.endTag(null, "atk"); serializer.startTag(null, "user"); serializer.text(weapon.getUser().trim()); serializer.endTag(null, "user"); //終止標籤: </weapon> serializer.endTag(null, "weapon"); } serializer.endTag("", "weapons");//標籤結束 serializer.endDocument();//文件結束 } catch (Exception e) { e.printStackTrace(); }finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
二、Sax解析概述:(Simple API for XML)
Sax解析方式會逐行地去掃描XML文件,當遇到標籤時會觸發解析處理器,採用事件處理的方式解析XML 優點:在讀取文件的同時即可對XML進行處理,不必等到文件載入結束,相對快捷,所以可以解析超大XML 缺點:只能用來讀取XML中資料,無法進行增刪改。
1、Sax解析Xml
/** * * @return */ private ArrayList<WeaponXml> parseXmlWithSax() { InputStream is = null; mWeapons = new ArrayList<>(); try { SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); is = getAssets().open("weapon.xml"); saxParser.parse(is, new DefaultHandler() { /** *開始標籤時 * @param uri 名稱空間 * @param localName 標籤名 * @param qName 全名(帶名稱空間的標籤的名字) * @param attributes 屬性 * @throws SAXException */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //"屬性名:" + attributes.getLocalName(i) //"屬性值:" + attributes.getValue(i)); if ("weapon".equals(localName)) { mWeapon = new WeaponXml(); mWeapon.setMaterial(attributes.getValue(0)); mWeapon.setType(attributes.getValue(1)); } mPerTag = localName; } /**解析標籤的內容的時候呼叫 * * @param ch 當前文字節點的位元組陣列 * @param start 位元組開始的位置 預設 0 全部讀取 * @param length 長度 * @throws SAXException */ @Override public void characters(char[] ch, int start, int length) throws SAXException { String chars = new String(ch, start, length).trim(); if ("name".equals(mPerTag)) { mWeapon.setName(chars); } else if ("atk".equals(mPerTag)) { mWeapon.setAtk(Integer.parseInt(chars)); } else if ("user".equals(mPerTag)) { mWeapon.setUser(chars); } } /** * 標籤解析結束呼叫 * @param uri * @param localName * @param qName * @throws SAXException */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("weapon".equals(localName)) { mWeapons.add(mWeapon); mWeapon = null; } mPerTag = null; } }); } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return mWeapons; }
2、Sax儲存Xml
/** * sax建立Xml檔案 */ private void saxCreateXml() { ArrayList<WeaponXml> weaponXmls = parseXmlWithSax(); //1、建立一個SAXTransformerFactory的物件 SAXTransformerFactory saxTF = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); FileOutputStream fos = null; try { //建立一個Transformer物件 TransformerHandler handler = saxTF.newTransformerHandler(); Transformer transformer = handler.getTransformer(); transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); String path = Environment.getExternalStorageDirectory().getAbsolutePath(); fos = new FileOutputStream(path + File.separator + "weaponSax.xml"); StreamResult result = new StreamResult(fos); handler.setResult(result); //開始 handler.startDocument(); AttributesImpl atts = new AttributesImpl(); handler.startElement("", "", "weapons", atts); for (WeaponXml weaponXml : weaponXmls) { atts.clear(); atts.addAttribute("", "", "material", "", weaponXml.getMaterial()); atts.addAttribute("", "", "type", "", weaponXml.getType()); handler.startElement("", "", "weapon", atts); atts.clear(); handler.startElement("", "", "name", atts); handler.characters(weaponXml.getName().toCharArray(), 0, weaponXml.getName().length()); handler.endElement("", "", "name"); atts.clear(); handler.startElement("", "", "atk", atts); String atk = String.valueOf(weaponXml.getAtk()); handler.characters(atk.toCharArray(), 0, atk.length()); handler.endElement("", "", "atk"); atts.clear(); handler.startElement("", "", "user", atts); handler.characters(weaponXml.getUser().toCharArray(), 0, weaponXml.getUser().length()); handler.endElement("", "", "user"); handler.endElement("", "", "weapon"); } handler.endElement("", "", "weapons"); //關閉document handler.endDocument(); } catch (Exception e) { e.printStackTrace(); }finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
三、DOM解析概述:
DOM將整個XML檔案載入到記憶體中,並構建出節點樹; 應用程式可以通過遍歷節點樹的方式來解析XML檔案中的各個節點、屬性等資訊; 優點:對XML節點的新增修改等,而且解析也很方便 缺點比較耗費記憶體,解析速度也不快
1、dom解析Xml
/** * dom解析Xml * @return */ private ArrayList<WeaponXml> parseXmlWithDom() { mWeapons = new ArrayList<>(); InputStream is = null; try { is = getAssets().open("weapon.xml"); //獲取document物件 Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is); //獲取根元素 Element root = dom.getDocumentElement(); //獲取weapon節點 NodeList weaponNode = root.getElementsByTagName("weapon"); for (int i = 0; i < weaponNode.getLength(); i++) { mWeapon = new WeaponXml(); //獲取person下第i個元素 Element weaponEl = (Element) weaponNode.item(i); String material = weaponEl.getAttribute("material");//得到第i個屬性值 String type = weaponEl.getAttribute("type");//得到第i個屬性值 mWeapon.setMaterial(material); mWeapon.setType(type); NodeList childNodes = weaponEl.getChildNodes();//獲得獲取weapon下子元素 for (int j = 0; j < childNodes.getLength(); j++) { if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE) { String nodeName = childNodes.item(j).getNodeName(); if ("name".equals(nodeName)) { String name = childNodes.item(j).getFirstChild().getNodeValue(); mWeapon.setName(name); } else if ("atk".equals(nodeName)) { String atk = childNodes.item(j).getFirstChild().getNodeValue(); mWeapon.setAtk(Integer.parseInt(atk)); } else if ("user".equals(nodeName)) { String user = childNodes.item(j).getFirstChild().getNodeValue(); mWeapon.setUser(user); } } } mWeapons.add(mWeapon); } } catch (Exception e) { e.printStackTrace(); } return mWeapons; }
2、dom儲存Xml
/** * sax建立Xml檔案 */ private void domCreateXml() { try { ArrayList<WeaponXml> weaponXmls = parseXmlWithDom(); //建立Dom解析器 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); //新建空白文件 Document doc = builder.newDocument(); //建立根元素employees Element root = doc.createElement("weapons"); //將根節點新增進入文件 doc.appendChild(root); for (WeaponXml weaponXml : weaponXmls) { Element weapon = doc.createElement("weapon"); weapon.setAttribute("material", weaponXml.getMaterial()); weapon.setAttribute("type", weaponXml.getType()); root.appendChild(weapon); Element name = doc.createElement("name"); name.appendChild(doc.createTextNode(weaponXml.getName())); weapon.appendChild(name); Element atk = doc.createElement("atk"); atk.appendChild(doc.createTextNode(weaponXml.getAtk()+"")); weapon.appendChild(atk); Element user = doc.createElement("user"); user.appendChild(doc.createTextNode(weaponXml.getUser())); weapon.appendChild(user); } //為了得到xslt引擎建立物件 TransformerFactory tff = TransformerFactory.newInstance(); //建立xslt引擎物件輸出xml文件 Transformer tf = tff.newTransformer(); //獲取屬性物件 Properties pro = tf.getOutputProperties(); //設定編碼格式和輸出格式 pro.setProperty(OutputKeys.ENCODING, "utf-8"); pro.setProperty(OutputKeys.METHOD, "xml"); tf.setOutputProperties(pro); //建立資源物件 DOMSource source = new DOMSource(doc); String path = Environment.getExternalStorageDirectory().getAbsolutePath() +File.separator+"WeaponDom.xml"; //獲得輸出物件 StreamResult result = new StreamResult(new File(path)); //執行dom文件到xml檔案轉換 tf.transform(source, result); } catch (Exception e) { e.printStackTrace(); }
後記:捷文規範
1.本文成長記錄及勘誤表
專案原始碼 | 日期 | 備註 |
---|---|---|
V0.1--無 | 2018-10-15 | ofollow,noindex">4--安卓網路程式設計之XML總彙篇 |
2.更多關於我
筆名 | 微信 | 愛好 | |
---|---|---|---|
張風捷特烈 | 1981462002 | zdl1994328 | 語言 |
我的github | 我的簡書 | 我的CSDN | 個人網站 |
3.宣告
1----本文由張風捷特烈原創,轉載請註明
2----歡迎廣大程式設計愛好者共同交流
3----個人能力有限,如有不正之處歡迎大家批評指證,必定虛心改正
4----看到這裡,我在此感謝你的喜歡與支援