XML解析--SAX

作者: MrMagicWang | 来源:发表于2016-08-24 22:50 被阅读60次
    XML结构
    <title>       hello      </title>
    标签开始     文本         标签结束
    
    事件模型

    SAX处理XML数据是采用事件的形式来处理,下面我们来简单的做个介绍:

    当我们处理XML数据中遇到一个开始标签后SAX会告诉你“我遇到了一个开始标签,这个标签是XXXX”,等你作出反应后,它会继续往下,这时它遇到了一段文本,SAX告诉你“我遇到了一段文本,是XXXX”,然后继续等你作出反应,接着下去就遇到了结束标签,SAX仍然会告诉你“我到了一个结束标签是XXX”。SAX就是以这样的方式将整个XML数据全部处理完。

    为何使用SAX解析XML
    • 节约内存
    • 效率高
      SAX解析XML文件采用的是事件驱动,它不需要解析整个文档,而是在解析文档的过程中,判断读到的字符是否符合XML语法的某部分,符合的话就会触发事件(回调方法)。
    相关类或方法
    类或方法 描述
    DefaultHandler类 安卓中内置的用于SAX处理XML的类,但是大多情况下我们都需要继承该类重写部分方法,才能达到处理XML数据的功能。
    startDocument 每处理一个XML文档都会响应一次。所以这个方法里可以写需要初始化的代码。
    startElement 处理每个节点所触发的方法。
    characters 处理一个节点之间的文本时候触发该方法,但是该方法并不会告诉你当前文本的所属标签,而仅仅是告诉你文本内容。
    endElement 遇到一个节点的结束标签时,将会出发这个方法,并且会传递结束标签的名称。
    endDocument 如果当前的XML文档处理完毕后,将会触发该方法,在此方法内你可以将最终的结果保存并且销毁不需要使用的变量。
    执行流程

    xml文件

    <notic>
       <id>1</id>
       <title>%3cs%3edsds%3c%2fs%3e</title>
       <content>%e5%86%85%e5%ae%b91</content>
       <author>1</author>
    </notic>
    

    响应过程:

    方法名称 localName(标签名称) ch[](文本名称)
    startDocument -- --
    startElement notic --
    startElement id --
    characters -- 1
    endElement id --
    startElement title --
    characters -- %3cs%3edsds%2c%2fs%3e
    endElement title --
    startElement content --
    characters -- %e5%86%85%e5%ae%b91
    endElement content --
    startElement author --
    characters -- 1
    endElement author --
    endElement notic --
    endDocument -- --
    localName和qName的区别
    <?xml version="1.0" encoding="utf-8"?>  
    <websites  
        xmlns:sina="http://www.sina.com"  
        xmlns:baidu="http://www.baidu.com">  
          
        <sina:website sina:blog="blog.sina.com">新浪</sina:website>  
        <baidu:website baidu:blog="hi.baidu.com">百度</baidu:website>  
    </websites>  
    

    Namespace(空间名称,命名空间)
    引入的原因是为了避免混淆。例如上面的这个XML文档,sina和baidu都有blog属性,定义了两个namespace,就像sax官网说的,用namespace是为了实现更多的扩展功能,作为基本应用,很多时候都用不到它:
    sina的namespace: http://www.sina.com
    baidu的namespace:http://www.baidu.com

    xmlns:sina="http://www.sina.com"  
    xmlns:baidu="http://www.baidu.com">  
    

    namespace的值可以任意,但是注意不要重复。一般默认的格式都是以url来作为namespace,比如
    xmlns:android="http://schemas.android.com/apk/res/android

    Prefix(前缀)
    sina:blog中 sina就是前缀。

    LocalName(本地名称)
    sina:blog 中blog就是localName。

    QName(Qualified Name 限定?指定?名称)
    sina:blog就是QName,相当于前缀+":"+LocalName。

    uri(不是url)
    例如sina:blog的uri就是前缀sina的namespace,即"http://www.sina.com"。

    例子

    xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <employees>
        <employee>
            <id>2163</id>
            <name>Kumar</name>
            <department>Development</department>
            <type>Permanent</type>      
            <email>kumar@tot.com</email>
        </employee>
        <employee>
            <id>6752</id>
            <name>Siva</name>
            <department>DB</department>
            <type>Contract</type>       
            <email>siva@tot.com</email>
        </employee>   
        <employee>
            <id>6763</id>
            <name>Timmy</name>
            <department>Testing</department>
            <type>Permanent</type>      
            <email>timmy@tot.com</email>
        </employee>
    </employees>
    

    Employee类

    public class Employee {
        private String name;
        private int id;
        private String department;
        private String type;
        private String email;
     
        public String getName() {
            return name;
        }
     
        public void setName(String name) {
            this.name = name;
        }
     
        public int getId() {
            return id;
        }
     
        public void setId(int id) {
            this.id = id;
        }
     
        public String getDepartment() {
            return department;
        }
     
        public void setDepartment(String department) {
            this.department = department;
        }
     
        public String getType() {
            return type;
        }
     
        public void setType(String type) {
            this.type = type;
        }
     
        public String getEmail() {
            return email;
        }
     
        public void setEmail(String email) {
            this.email = email;
        }
     
        @Override
        public String toString() {
            return id + ": " + name;
        }
     
        public String getDetails() {
            String result = id + ": " + name + "\n" + department + "-" + type
                    + "\n" + email;
            return result;
        }
    }
    

    创建一个类继承DefaultHandler类

    public class SAXXMLHandler extends DefaultHandler {
     
        private List<Employee> employees;
        private String tempVal;
        private Employee tempEmp;
     
        public SAXXMLHandler() {
            employees = new ArrayList<Employee>();
        }
     
        public List<Employee> getEmployees() {
            return employees;
        }
     
        // Event Handlers
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            // reset
            tempVal = "";
            if (qName.equalsIgnoreCase("employee")) {
                // create a new instance of employee
                tempEmp = new Employee();
            }
        }
     
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            tempVal = new String(ch, start, length);
        }
     
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            if (qName.equalsIgnoreCase("employee")) {
                // add it to the list
                employees.add(tempEmp);
            } else if (qName.equalsIgnoreCase("id")) {
                tempEmp.setId(Integer.parseInt(tempVal));
            } else if (qName.equalsIgnoreCase("name")) {
                tempEmp.setName(tempVal);
            } else if (qName.equalsIgnoreCase("department")) {
                tempEmp.setDepartment(tempVal);
            } else if (qName.equalsIgnoreCase("type")) {
                tempEmp.setType(tempVal);
            } else if (qName.equalsIgnoreCase("email")) {
                tempEmp.setEmail(tempVal);
            }
        }
    }
    

    创建XML解析类

    public class SAXXMLParser {
        public static List<Employee> parse(InputStream is) {
            List<Employee> employees = null;
            try {
                // create a XMLReader from SAXParser
                XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser()
                        .getXMLReader();
                // create a SAXXMLHandler
                SAXXMLHandler saxHandler = new SAXXMLHandler();
                // store handler in XMLReader
                xmlReader.setContentHandler(saxHandler);
                // the process starts
                xmlReader.parse(new InputSource(is));
                // get the `Employee list`
                employees = saxHandler.getEmployees();
     
            } catch (Exception ex) {
                Log.d("XML", "SAXXMLParser: parse() failed");
            }
     
            // return Employee list
            return employees;
        }
    }
    

    使用SAXXMLParser

    List<Employee> employees = SAXXMLParser.parse(getAssets().open("employees.xml"));
    

    相关文章

      网友评论

        本文标题:XML解析--SAX

        本文链接:https://www.haomeiwen.com/subject/oqyosttx.html