天天看點

Android 使用Dom與SAX解析xml文檔的方式

package com.example.lxb.awaken.model;


import com.example.lxb.awaken.SpeechApp;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;


import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * 使用Sax解析xml文檔
 * <p>
 * Created by lxb on 2017/4/26.
 */

public class ParseXMLSAX {

    private static ParseXMLSAX parseXMLSAX;

    public static ParseXMLSAX getInstance(){

        if(parseXMLSAX == null){

            parseXMLSAX = new ParseXMLSAX();
        }
        return parseXMLSAX;
    }

    /**
     * 擷取assets檔案
     *
     * @param path
     * @return
     */
    public InputStream getFileInputStream(String path) {

        try {

            return SpeechApp.getInstance().getAssets().open(path);

        } catch (IOException e) {

            e.printStackTrace();
        }

        return null;
    }

    /**
     * 解析xml文檔
     * 
     * @param path
     * @return
     * @throws Exception
     */
    public List<VoiceEntity> parse(String path) throws Exception {

        InputStream is = getFileInputStream(path);

        SAXParserFactory factory = SAXParserFactory.newInstance();

        SAXParser parser = factory.newSAXParser();

        SaxXmlHandler handler = new SaxXmlHandler();

        parser.parse(is, handler);

        return handler.getvoiceEntitys();
    }

    /**
     * DefaultHandler是一個事件處理器,可以接收解析器報告的所有事件,處理所發現的資料
     *
     */
    private class SaxXmlHandler extends DefaultHandler {

        private List<VoiceEntity> voiceEntitys;
        private VoiceEntity voiceEntity;
        private StringBuilder builder;


        public List<VoiceEntity> getvoiceEntitys() {
            return voiceEntitys;
        }

        @Override
        public void startDocument() throws SAXException {
            // TODO Auto-generated method stub
            super.startDocument();
            voiceEntitys = new ArrayList<>();
            builder = new StringBuilder();
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            // TODO Auto-generated method stub
            super.startElement(uri, localName, qName, attributes);

            if (localName.equals("item")) {

                voiceEntity = new VoiceEntity();
            }

            builder.setLength(0);
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            // TODO Auto-generated method stub
            super.characters(ch, start, length);
            builder.append(ch, start, length);                  //将讀取的字元數組追加到builder中
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            // TODO Auto-generated method stub
            super.endElement(uri, localName, qName);

            if (localName.equals("id")) {

                voiceEntity.setID(Integer.parseInt(builder.toString()));

            } else if (localName.equals("type")) {

                voiceEntity.setType(Integer.parseInt(builder.toString()));

            } else if (localName.equals("key")) {

                voiceEntity.setKey(Integer.parseInt(builder.toString()));

            } else if (localName.equals("cmd")) {

                voiceEntity.setCmd(builder.toString());

            } else if (localName.equals("item")) {

                voiceEntitys.add(voiceEntity);
            }

        }

    }
}      

對外接口類:

package com.example.lxb.awaken.speech.util;

import com.example.lxb.awaken.SpeechApp;
import com.example.lxb.awaken.model.ParseXMLSAX;
import com.example.lxb.awaken.model.VoiceEntity;
import com.iflytek.cloud.util.ResourceUtil;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

/**
 * Xml結果解析類
 */
public class XmlParser {

   public static String parseNluResult(String xml) 
   {
      StringBuffer buffer = new StringBuffer();
      try
      {
         // DOM builder
         DocumentBuilder domBuilder = null;
         // DOM doc
         Document domDoc = null;    

         // init DOM
         DocumentBuilderFactory domFact = DocumentBuilderFactory.newInstance();
         domBuilder = domFact.newDocumentBuilder();
         InputStream is = new ByteArrayInputStream(xml.getBytes());
         domDoc = domBuilder.parse(is);

         // 擷取根節點
         Element root = (Element) domDoc.getDocumentElement();
         
         Element raw = (Element)root.getElementsByTagName("rawtext").item(0);
         buffer.append("【識别結果】" + raw.getFirstChild().getNodeValue());
         buffer.append("\n");
         
         Element e = (Element)root.getElementsByTagName("result").item(0);
         
         Element focus = (Element)e.getElementsByTagName("focus").item(0);
         buffer.append("【FOCUS】" + focus.getFirstChild().getNodeValue());
         buffer.append("\n");
         
         Element action = (Element)e.getElementsByTagName("action").item(0);
         Element operation = (Element)action.getElementsByTagName("operation").item(0);
         buffer.append("【ACTION】" + operation.getFirstChild().getNodeValue());
         buffer.append("\n");
         

      }catch(Exception e){
         e.printStackTrace();
      };
      buffer.append("【ALL】" + xml);
      return buffer.toString();
   }


   /**
    * 使用DOM解析方式
    * DOM是基于樹形結構的的節點或資訊片段的集合,允許開發人員使用DOM API周遊XML樹、檢索所需資料。
    * 分析該結構通常需要加載整個文檔和構造樹形結構,然後才可以檢索和更新節點資訊。
    * 由于DOM在記憶體中以樹形結構存放,是以檢索和更新效率會更高。但是對于特别大的文檔,解析和加載整個文檔将會很耗資源。
    *
    *
    * @param path
    * @return
    */
   public static List<VoiceEntity> parseXMLByDom(String path){

      InputStream is = null;
      try {
         is = SpeechApp.getInstance().getAssets().open(path);



         List<VoiceEntity> s  = new ArrayList<>();
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  //取得DocumentBuilderFactory執行個體
         DocumentBuilder builder = factory.newDocumentBuilder();             //從factory擷取DocumentBuilder執行個體


         Document doc = builder.parse(is);   //解析輸入流 得到Document執行個體
         Element rootElement = doc.getDocumentElement();
         NodeList items = rootElement.getElementsByTagName("item");

         for (int i = 0; i < items.getLength(); i++) {
            VoiceEntity depart = new VoiceEntity();
            Node item = items.item(i);
            NodeList properties = item.getChildNodes();
            for (int j = 0; j < properties.getLength(); j++) {
               Node property = properties.item(j);
               String nodeName = property.getNodeName();
               if (nodeName.equals("ID")) {
                  depart.setID(Integer.parseInt(property.getFirstChild().getNodeValue()));
               } else if (nodeName.equals("type")) {
                  depart.setType(Integer.parseInt(property.getFirstChild().getNodeValue()));
               } else if (nodeName.equals("key")) {
                  depart.setKey(Integer.parseInt(property.getFirstChild().getNodeValue()));
               }
            }
                s.add(depart);
         }

         return s;

      } catch (IOException e) {
         e.printStackTrace();
      } catch (ParserConfigurationException e) {
         e.printStackTrace();
      } catch (SAXException e) {
         e.printStackTrace();
      }


      return null;

   }

   /**
    * SAX:優點是解析速度快,占用記憶體少。非常适合在Android移動裝置中使用
    *
    * @param path
    */
   public static List<VoiceEntity> parseXMLBySAX(String path){

      try {
         return ParseXMLSAX.getInstance().parse(path);

      } catch (Exception e) {
         e.printStackTrace();

      }

      return null;

   }


}
      

資訊實體類:

package com.example.lxb.awaken.model;

/**
 * Created by lxb on 2017/4/26.
 */

public class VoiceEntity extends XMLBase{


    private int ID;

    private int type;

    private int key;

    private String cmd;

    public int getID() {
        return ID;
    }

    public void setID(int ID) {
        this.ID = ID;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public int getKey() {
        return key;
    }

    public void setKey(int key) {
        this.key = key;
    }

    public String getCmd() {
        return cmd;
    }

    public void setCmd(String cmd) {
        this.cmd = cmd;
    }


}
      

測試接口:

long start = System.currentTimeMillis();
try {
    System.out.println("88-----------"+XmlParser.parseXMLBySAX("volinfo.xml").size()); //檔案記得放在assets目錄下
    long end = System.currentTimeMillis();

} catch (Exception e) {
    e.printStackTrace();
}      

volinfo.xml檔案内容:

<?xml version="1.0" encoding="UTF-8"?>  
<volbook>  
  
    <!-- 音量加 -->
    <item>                    
        
       <ID>0</ID>  
        <type>1</type>  
        <key>518</key>  
        <cmd>no</cmd>  
    </item>  
    
       <!-- 音量減 -->
      <item>                
        
        <ID>1</ID> 
          
        <type>1</type>  
        <key>517</key>  
        <cmd>no</cmd>  
    </item>  
    
    <!-- 亮度加 -->
    <item>                 
        
        <ID>2</ID> 
          
        <type>1</type>  
        <key>520</key>  
        <cmd>no</cmd>  
    </item>  
    
     <!-- 亮度減 -->
    <item>                 
        
       <ID>3</ID> 
          
        <type>1</type>  
        <key>519</key>  
        <cmd>no</cmd>  
    </item>  
    
     <!-- 關機操作 -->
    <item>                  
        
       <ID>4</ID> 
          
        <type>0</type>  
        <key>506</key>  
        <cmd>reboot -p</cmd>             
    </item>  
  
     <!-- 待機功能 -->
    <item>                 
        
       <ID>5</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>  
    
    
    <!-- 照相機調用  錄影機呼出 -->
    <item>          
        
       <ID>6</ID>
          
        <type>1</type>  
        <key>601</key>  
        <cmd>no</cmd>  
    </item>  
    
    
     <item>          
        
       <ID>7</ID>
          
        <type>1</type>  
        <key>601</key>  
        <cmd>no</cmd>  
    </item>  
   
       <!-- 音樂功能 -->
    <item>               
        
       <ID>8</ID>
          
        <type>1</type>  
        <key>600</key>  
        <cmd>no</cmd>  
    </item>  
      
     <!-- 電影功能 -->
    <item>           
        
       <ID>9</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>am start -n  com.actions.demomovie/.FileBrowserActivity</cmd>  
    </item>  
    
    
     <!-- 系統設定 -->
    <item>            
        
       <ID>10</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>am start -n com.android.settings/.Settings</cmd>  
    </item>  


       <!-- 浏覽器功能 -->
    <item>                
        
        <ID>11</ID>
          
        <type>1</type>  
        <key>602</key>  
        <cmd>am start  -n  com.android.browser/.BrowserActivity</cmd>     
    </item>  
      
     <!-- 電腦功能 -->
    <item>            
        
      <ID>12</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>am start  -n  com.android.calculator2/.Calculator</cmd>  
    </item>      

    
       <!-- 圖庫功能 -->
    <item>            
        
         <ID>13</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>am start -n com.android.gallery3d/.app.GalleryActivity</cmd>  
    </item>    
    
    
       <!-- 單屏功能 -->
      <item>       
        
         <ID>14</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>      
 
   <!-- 多屏功能 -->
    <item>       
        
       <ID>15</ID>
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>    
      
      <!-- 界面管理功能 -->
    <item>        
        
       <ID>16</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>am start -n com.actions.arlauncher/.AllAppActivity</cmd>  
    </item>      
    
    <!-- 郵件 -->
    <item>         
        
        <ID>17</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>am start -n  com.android.email/.activity.Welcome</cmd>  
    </item>       
    
    <!-- 百事通 -->
    <item>      
        
        <ID>18</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>       
    
    <!-- 微信 -->
    <item>      
        
        <ID>19</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>am start -n com.tencent.mm/.ui.LauncherUI</cmd>  
    </item>          
       
     <!-- QQ -->
    <item>   
        
         <ID>20</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>am start -n com.tencent.mobileqq/.activity.SplashActivity</cmd>  
    </item>          

       <!-- 花椒 -->
    <item>     
        
        <ID>21</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>              
  
   <!-- 酷我音樂 -->
    <item>      
        
        <ID>22</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>      
   
      <!-- 百度音樂 -->
    <item>    
        
        <ID>23</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>         
   
       <!-- 百度地圖 -->
    <item>     
        
       <ID>24</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>       
    
     <!-- 高德導航 -->
    <item>    
        
       <ID>25</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>       
    
    <!-- 取消關機 -->
    <item>     
        
       <ID>26</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>       
    
    <!-- 确認關機 -->
    <item>     
        
        <ID>27</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>      

      <!-- 确認待機 -->
    <item>   
        
       <ID>28</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>                   
 
         <!-- 取消待機 -->
     <item>    
        
       <ID>29</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>                   

      <!-- 拍攝一張照片 -->
     <item>    
        
       <ID>30</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>                   
 
 
      <!-- 開始攝像 -->
     <item>      
        
         <ID>31</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>                   

     <!-- 停止攝像 -->
     <item>    
        
         <ID>32</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>                   
                  
      <!-- wifi功能  -->                    
     <item>    
        
        <ID>33</ID>
          
        <type>0</type>  
        <key>506</key>  
        <cmd>am start -n com.android.settings/.Settings\$WifiSettingsActivity</cmd>  
    </item>              
    
      <!-- 電池功能 -->
     <item>     
        
        <ID>34</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>      
    
    
    <!-- 藍牙功能打開  -->
       <item>     
        
        <ID>35</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>              
    
     <!-- 藍牙功能關閉 -->
     <item>    
        
        <ID>36</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>                              
                
     <!-- 顯示功能 -->      
    <item>    
        
        <ID>37</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>         
    
       <!-- 傳回,退出  -->    
    <item>    
        
        <ID>38</ID>
          
        <type>1</type>  
        <key>506</key>  
        <cmd>no</cmd>  
    </item>   
    
    
        <item>         
          <ID>39</ID>         
        <type>1</type>  
        <key>502</key>  
        <cmd>no</cmd>  
    </item>  
    
  
</volbook>