• 技术文章 >后端开发 >XML/RSS教程

    XML—XML解析之SAX

    黄舟黄舟2017-02-24 15:06:59原创930

    1.SAX解析

    【注意】SAX主要用于对XML文档的解析,不能去修改、删除和添加元素。

    1.1.SAX解析机制

    sax是一种推式的机制,你创建一个sax解析器,解析器在发现xml文档中的内容时就告诉你(把事件推给你,有点类似于java swing中的事件监听)。如何处理这些发现的内容,由程序员自己决定。

    在基于sax的程序中,有五个最常用的sax事件:

    1.startDocument()–>告诉你解析器发现了文档的开始,告诉你解析器开始扫描文档
    2.endDocument()–>告诉你解析器发现了文档结尾
    3.startElement()–>告诉你解析器发现了一个起始标签,该事件告诉你标签的名称、该元素所有的属性名和值
    4.characters()–>告诉你解析器发现了一些文本,将得到一个字符数组,该数组的偏移量和一个长度偏移量,有这三个变量你可以得到解析器发现的文本
    5.endElement()–>告诉你解析器发现了一个结束标签,该事件告诉你元素的名称

    1.2.SAX解析实例

    依然使用DOM解析中用到的XML例子,如下:

    <?xml version="1.0" encoding="utf-8" standalone="no"?><班级>
        <学生 地址="香港">
            <名字>周小星</名字>
            <年龄>23</年龄>
            <介绍>学习刻苦</介绍>
        </学生>
        <学生 地址="澳门">
            <名字>林晓</名字>
            <年龄>25</年龄>
            <介绍>是一个好学生</介绍>
        </学生></班级>

    【步骤】:

    1.使用SAXParserFactory创建SAX解析工厂

    SAXParserFactory spf = SAXParserFactory.newInstance();

    2.通过SAX解析工厂得到解析器对象

    SAXParser sp = spf.newSAXParser();

    3.将解析对象和事件处理器对象关联

    sp.parse("src/myClass.xml",new MyHandler());

    这里的MyHandler需要自己定义,并且它要继承DefaultHandler,然后在MyHandler类中重写上文提到的5个sax事件方法,当然也可以只重写自己需要的。
    比如现在我写的MyHandler如下:

    class MyHandler extends DefaultHandler{    /**
         * 发现文档开始,该函数只会被调用一次
         */
        @Override
        public void startDocument() throws SAXException {
            System.out.println("startDocument");
        }    /**
         * 发现文档结束,该函数只会被调用一次
         */
        @Override
        public void endDocument() throws SAXException {
            System.out.println("endDocument");
        }    /**
         * 发现XML中的一个元素开始,会被反复调用
         */
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            System.out.println("元素名称:"+qName);
        }    /**
         * 发现XML中的一个元素结束,会被反复调用
         */
        @Override
        public void endElement(String uri, String localName, String qName)            
        throws SAXException {
    
        }    /**
         * 发现XML文件中的文本,会被反复调用
         */
        @Override
        public void characters(char[] ch, int start, int length)            
        throws SAXException {        // 显示文本内容
            String text = new String(ch,start,length);        if(!text.trim().equals("")){
                System.out.println(text);
            }
        }
    }

    运行结果如下:

    运行结果1

    可以看到,这是对XML文档的一种遍历,而sax能够做的也只是遍历了。


    那么,如果现在我们有这样一个需求:只显示所有学生的姓名和年龄,不显示学生的介绍,怎么实现呢?

    我们可以在MyHandler类中定义两个布尔变量isName和isAge,在startElement方法中标识是否是姓名元素或者年龄元素,如果是的话才在characters方法中获取对应的文本,如下:

    1.定义两个布尔变量

    private boolean isName = false;private boolean isAge = false;

    2.在startElement方法中添加判断

    @Overridepublic void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {    if(qName.equals("名字")){        this.isName = true;
        }else if(qName.equals("年龄")){        this.isAge = true;
        }
    }

    3.在characters方法中根据标识符进行判断是否获取文本

    @Overridepublic void characters(char[] ch, int start, int length)        throws SAXException {    // 显示文本内容
        String text = new String(ch,start,length);    if(!text.trim().equals("")&&(isName||isAge)){
            System.out.println(text);
        }
        isName = false;
        isAge = false;
    }

    最后要记得将两个布尔变量复位成false。
    运行结果如下:

    运行结果2

    1.SAX解析

    【注意】SAX主要用于对XML文档的解析,不能去修改、删除和添加元素。

    1.1.SAX解析机制

    sax是一种推式的机制,你创建一个sax解析器,解析器在发现xml文档中的内容时就告诉你(把事件推给你,有点类似于java swing中的事件监听)。如何处理这些发现的内容,由程序员自己决定。

    在基于sax的程序中,有五个最常用的sax事件:

    1.startDocument()–>告诉你解析器发现了文档的开始,告诉你解析器开始扫描文档
    2.endDocument()–>告诉你解析器发现了文档结尾
    3.startElement()–>告诉你解析器发现了一个起始标签,该事件告诉你标签的名称、该元素所有的属性名和值
    4.characters()–>告诉你解析器发现了一些文本,将得到一个字符数组,该数组的偏移量和一个长度偏移量,有这三个变量你可以得到解析器发现的文本
    5.endElement()–>告诉你解析器发现了一个结束标签,该事件告诉你元素的名称

    1.2.SAX解析实例

    依然使用DOM解析中用到的XML例子,如下:

    <?xml version="1.0" encoding="utf-8" standalone="no"?><班级>
        <学生 地址="香港">
            <名字>周小星</名字>
            <年龄>23</年龄>
            <介绍>学习刻苦</介绍>
        </学生>
        <学生 地址="澳门">
            <名字>林晓</名字>
            <年龄>25</年龄>
            <介绍>是一个好学生</介绍>
        </学生></班级>

    【步骤】:

    1.使用SAXParserFactory创建SAX解析工厂

    SAXParserFactory spf = SAXParserFactory.newInstance();

    2.通过SAX解析工厂得到解析器对象

    SAXParser sp = spf.newSAXParser();

    3.将解析对象和事件处理器对象关联

    sp.parse("src/myClass.xml",new MyHandler());

    这里的MyHandler需要自己定义,并且它要继承DefaultHandler,然后在MyHandler类中重写上文提到的5个sax事件方法,当然也可以只重写自己需要的。
    比如现在我写的MyHandler如下:

    class MyHandler extends DefaultHandler{    /**
         * 发现文档开始,该函数只会被调用一次
         */
        @Override
        public void startDocument() throws SAXException {
            System.out.println("startDocument");
        }    /**
         * 发现文档结束,该函数只会被调用一次
         */
        @Override
        public void endDocument() throws SAXException {
            System.out.println("endDocument");
        }    /**
         * 发现XML中的一个元素开始,会被反复调用
         */
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            System.out.println("元素名称:"+qName);
        }    /**
         * 发现XML中的一个元素结束,会被反复调用
         */
        @Override
        public void endElement(String uri, String localName, String qName)            
        throws SAXException {
    
        }    /**
         * 发现XML文件中的文本,会被反复调用
         */
        @Override
        public void characters(char[] ch, int start, int length)            
        throws SAXException {        // 显示文本内容
            String text = new String(ch,start,length);        
            if(!text.trim().equals("")){
                System.out.println(text);
            }
        }
    }

    运行结果如下:

    运行结果1

    可以看到,这是对XML文档的一种遍历,而sax能够做的也只是遍历了。


    那么,如果现在我们有这样一个需求:只显示所有学生的姓名和年龄,不显示学生的介绍,怎么实现呢?

    我们可以在MyHandler类中定义两个布尔变量isName和isAge,在startElement方法中标识是否是姓名元素或者年龄元素,如果是的话才在characters方法中获取对应的文本,如下:

    1.定义两个布尔变量

    private boolean isName = false;private boolean isAge = false;

    2.在startElement方法中添加判断

    @Overridepublic void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {    if(qName.equals("名字")){        
            this.isName = true;
        }else if(qName.equals("年龄")){        this.isAge = true;
        }
    }

    3.在characters方法中根据标识符进行判断是否获取文本

    @Overridepublic void characters(char[] ch, int start, int length)        throws SAXException {    // 显示文本内容
        String text = new String(ch,start,length);    if(!text.trim().equals("")&&(isName||isAge)){
            System.out.println(text);
        }
        isName = false;
        isAge = false;
    }

    最后要记得将两个布尔变量复位成false。
    运行结果如下:

    运行结果2

    以上就是XML—XML解析之SAX的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!


    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:XML,SAX
    上一篇:XML—XML解析之DOM 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 详细介绍xml的语法的使用和学习• C#对XML读写的代码实例• 具体介绍历数Firefox2.0对XML处理的改进的代码实例(图)• Javascript 调用XML制作连动下拉框代码实例详解• XML轻松学习手册(2)XML概念
    1/1

    PHP中文网