【Java Web】——基于事件流的访问XML方式之推拉模型

前端之家收集整理的这篇文章主要介绍了【Java Web】——基于事件流的访问XML方式之推拉模型前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

在上篇博客中,我们介绍了两种访问XML的方式,一种是基于DOM文档的,另一种是基于SAX事件流的。在介绍面向事件访问方式的两种方法:SAX和STAX,提到了两个特别有意思的词:“推”模型和“拉”模型。


今天,我们就通过代码来看一下,它们是如何体现推和拉的。


【生活中的推拉模型】


在查找资料的时候,看到有人对这个推拉的比喻特别恰当。其实编程里面的一些词,都可以从现实生活中找到例子。例如这个推拉,就比如说发传单。发传单有两种方式:塞和取。前者是你经过的时候,发传单的人主动的扔给你,塞到你面前,而后者则向超市里的货架一样,摆在那里,等着你自己去取。


【编程中的推拉模型】


在我们的编程中的推拉,其实和现实生活中的推拉模型是一样的。它只不过是SAX方式解析XML的两种实现方法。其实,在我们的编程过程中也会遇到需要对某个对象进行监听,并在其发生变化的时候做出不同的反应情况。为实现此需求,我们有两种解决办法。


一、通过回调(CallBack)实现


定义一个函数,并且在其中编写变化处理语句,然后将其指针传递给被监听的对象,在被监听对象发生变化后,对其进行调用。这就是我们以事件为驱动的推模型(Event-driven programming)。就是对象发生改变的时候,用编写好的函数去处理这些参数。


二、通过轮询(Loop check)实现


不断去获取被监听对象的状态,在其改变后执行相应的语句。这就是拉模型,你获取被监听对象的状态,然后做出反应。


【SAX解析XML的推拉模型】


拉模型——STAX:获取XMLStreamReader的事件类型,然后执行相应的输出语句。

 /**
     * 读取Xml
     */
    public static void readDemo() throws FileNotFoundException,XMLStreamException {

        XMLInputFactory factory = XMLInputFactory.newInstance();
        InputStream input=new FileInputStream(new File("test.xml"));
        XMLStreamReader r = factory.createXMLStreamReader(input);
        try {
            int event = r.getEventType();
            while (true) {
                switch (event){
                    case XMLStreamConstants.START_DOCUMENT:   //文档开始

                        System.out.println("Start Document.");  
                        break;
                    case XMLStreamConstants.START_ELEMENT:    //节点开始

                        System.out.println("Start Element: " + r.getName());
                        for(int i = 0,n = r.getAttributeCount(); i < n; ++i)
                            System.out.println("Attribute: " + r.getAttributeName(i) + "=" + r.getAttributeValue(i));    //获取节点属性值
                        break;
                    case XMLStreamConstants.CHARACTERS:     //节点元素值
                        if (r.isWhiteSpace())
                            break;
                        System.out.println("Text: " + r.getText());   
                        break;
                    case XMLStreamConstants.END_ELEMENT:
                        System.out.println("End Element:" + r.getName());  //节点结束
                        break;
                    case XMLStreamConstants.END_DOCUMENT:
                        System.out.println("End Document.");    //文档结束
                        break;
                }
                if (!r.hasNext())
                    break;
                event = r.next();
            }
        } finally {
            r.close();
        }
    }


注:int event=r.getEventType();这行代码就是获取XMLStreamReader的事件类型,如果是文档开始,输出什么,如果是节点开始输出什么,如果是节点元素值,又输出什么,它是根据监听对象的变化,而执行不同的输出语句。


推模型——SAX:对象发生变化时,调用编写好的处理函数

public class test {

    public static void main(String[] args) throws SAXException,IOException {
        /*domDemo dd=new domDemo();
        String str = "D:/grade.xml";
        dd.init();
        //dd.createXML(str);
        dd.praseXML(str);*/
        //创建处理文档内容相关事件的处理器
        ContentHandler contentHandler = new MyContentHandler();
        //创建处理错误事件处理器
        ErrorHandler errorHandler = new MyErrorHandler();
        //创建处理DTD相关事件的处理器
        DTDHandler dtdHandler = new MyDTDHandler();
        //创建实体解析器
        EntityResolver entityResolver = new MyEntityResolver();

        //创建一个XML解析器(通过SAX方式读取解析XML)
        XMLReader reader = XMLReaderFactory.createXMLReader();
        /*
         * 设置解析器的相关特性
         *     http://xml.org/sax/features/validation = true 表示开启验证特性
         *     http://xml.org/sax/features/namespaces = true 表示开启命名空间特性
         */
        reader.setFeature("http://xml.org/sax/features/validation",true);
        reader.setFeature("http://xml.org/sax/features/namespaces",true);
        //设置XML解析器的处理文档内容相关事件的处理器
        reader.setContentHandler(contentHandler);
        //设置XML解析器的处理错误事件处理器
        reader.setErrorHandler(errorHandler);
        //设置XML解析器的处理DTD相关事件的处理器
        reader.setDTDHandler(dtdHandler);
        //设置XML解析器的实体解析器
        reader.setEntityResolver(entityResolver);
        //解析test.xml文档
        reader.parse(new InputSource(new FileReader("test.xml")));
    }

注:在SAX中,当contentHandler,errorHandler,dtdHandler,entityResolver对象发生变化时,会调用XMLReader实例对象reader中写好的set方法。上面这几个对象就是我们上篇博客里讲到的SAX的常用事件处理器。


【总结】


以上就是做了小Demo,然后上网查找资料,对于解析XML方式——SAX的推拉模型的一些简单理解,算是比较简单的啦,有些地方理解的不是很透彻,先挂起来吧,对于我来说,这个阶段还不适合深入研究呢,还是抓紧时间往下学习吧!

猜你在找的XML相关文章