• XML编程总结(五)——使用StAX接口操作xml


    (五)使用StAX接口操作xml

    StAX,全称Streaming API for XML,一种全新的,基于流的JAVA XML解析标准类库。其最终版本于 2004 年 3 月发布,并成为了 JAXP 1.4(将包含在即将发布的 Java 6 中)的一部分。在某种程度上来说,StAX与SAX一样是基于XML事件的解析方式,它们都不会一次性加载整个XML文件。但是它们之间也有很大的不同。

    StAX和SAX的区别——拉式解析器和推式解析器的区别

    虽然StAX与SAX一样基于XML事件解析,相比于DOM将整个XML加载进内存来说效率高。不同的是,StAX在在处理XML事件的方式上使得应用程序更接近底层,所以在效率上比SAX更优秀。

    使用SAX时,我们知道XML事件是由解析器调用开发人员编写的回调方法来处理的,也就是说应用程序是被动于解析器的。应用程序只能被动的等待解析器将XML事件推送给自己处理,对于每一种事件都需要在解析开始之前就做好准备。这种方式被称为“推(push)”。而StAX正好相反,StAX采用一种“拉(pull)”的方式,由应用程序主动从解析器中获取当前XML事件然后根据需求处理(保存或者忽略)。StAX使得应用程序掌握了主动权,可以简化调用代码来准确地处理它预期的内容,或者发生意外时停止解析。此外,由于该方法不基于处理程序回调,应用程序不需要像使用 SAX 那样模拟解析器的状态。

    基于指针的API:

    基于指针(Cursor)的 API 允许应用程序把 XML 作为一个标记(或事件)流来处理。在这里,解析器就像一跟指针一样在文件流上前进,应用程序可以跟随解析器从文件的开头一直处理到结尾。这是一种低层 API,尽管效率高,但是没有提供底层 XML 结构的抽象。Cursor API 由两个主要API组成,XMLStreamReader和XMLStreamWriter,分别由XMLInputStreamFactory和XMLOutputStreamFactory获取

    基于迭代器的API:

    基于迭代器的API允许应用程序把 XML 作为一系列事件对象来处理,每个对象和应用程序交换 XML 结构的一部分。应用程序只需要确定解析事件的类型,将其转换成对应的具体类型,然后利用其方法获得属于该事件的信息。基于事件迭代器的方法具有一个基于指针的方法不具备的重要优点。通过将解析器事件变成一级对象,从而让应用程序可以采用面向对象的方式处理它们。这样做有助于模块化和不同应用程序组件之间的代码重用。Iterator API 由两个主要API组成,XMLEventReader和XMLEventWriter,分别由XMLInputStreamFactory和XMLOutputStreamFactory获取

    测试代码

      1 public class StAXTest {
      2     private InputStream is;
      3 
      4     @Before
      5     public void setUp() throws Exception{
      6         is=StAXTest.class.getClassLoader()
      7                 .getResourceAsStream("books.xml");
      8     }
      9     
     10     /**
     11      * 基于指针的方式读取xml文档——XMLStreamReader
     12      * @throws Exception
     13      */
     14     @Test
     15     public void testRetrieveByCursor() throws Exception{
     16         //创建读取流工厂对象
     17         XMLInputFactory factory = XMLInputFactory.newInstance();
     18         //创建基于指针的读取流对象
     19         XMLStreamReader streamReader = factory.createXMLStreamReader(is);
     20         //用指针迭代
     21         while(streamReader.hasNext()){  
     22             //事件的ID
     23             int eventId=streamReader.next();  
     24             
     25             switch (eventId) {  
     26             case XMLStreamConstants.START_DOCUMENT:  
     27                 System.out.println("start docmuent");  
     28                 break;  
     29                   
     30             case XMLStreamConstants.START_ELEMENT:  
     31                 System.out.println("<"+streamReader.getLocalName()+">");  
     32                 for(int i=0;i<streamReader.getAttributeCount();i++){  
     33                     System.out.println(streamReader.getAttributeLocalName(i)+
     34                             "="+streamReader.getAttributeValue(i));  
     35                 }  
     36                 break;  
     37                   
     38             case XMLStreamConstants.CHARACTERS:  
     39                 if(streamReader.isWhiteSpace()){  
     40                     break;  
     41                 }  
     42                 System.out.println(streamReader.getText());  
     43                 break;  
     44             case XMLStreamConstants.END_ELEMENT:  
     45                 System.out.println("</"+streamReader.getLocalName()+">");  
     46                   
     47                 break;  
     48             case XMLStreamConstants.END_DOCUMENT:  
     49                 System.out.println("end docmuent");  
     50                 break;  
     51             default:  
     52                 break;  
     53             }  
     54         }  
     55     }
     56     
     57     /**
     58      * 基于迭代器的方式读取xml文档——XMLEventReader
     59      * @throws Exception
     60      */
     61     @Test
     62     public void testRetrieveByIterator() throws Exception{
     63         //创建读取流工厂对象
     64         XMLInputFactory factory = XMLInputFactory.newInstance();
     65         //创建基于迭代器(事件流对象)的流对象
     66         XMLEventReader eventReader = factory.createXMLEventReader(is);
     67         //迭代xml文档
     68         while (eventReader.hasNext()) {
     69             //得到具体的 事件对象,就是引发事件的对象(可以是元素节点、文本节点、属性节点)
     70             XMLEvent event = eventReader.nextEvent();
     71 
     72             switch (event.getEventType()) {
     73             case XMLStreamConstants.START_DOCUMENT:
     74                 System.out.println("start docmuent");
     75                 break;
     76 
     77             case XMLStreamConstants.START_ELEMENT:
     78                 //将事件对象可以转换为元素节点对象
     79                 StartElement element = (StartElement) event;
     80                 System.out.println("<" + element.getName().getLocalPart() + ">");
     81                 for (Iterator it = element.getAttributes(); it.hasNext();) {
     82                     Attribute attr = (Attribute) it.next();
     83                     System.out.println(attr.getName().getLocalPart() + "=" + attr.getValue());
     84                 }
     85                 break;
     86 
     87             case XMLStreamConstants.CHARACTERS:
     88                 //将事件对象可以转换成文本节点
     89                 Characters charData = (Characters) event;
     90                 if (charData.isIgnorableWhiteSpace() && charData.isWhiteSpace()) {
     91                     break;
     92                 }
     93                 System.out.println(charData.getData());
     94                 break;
     95             case XMLStreamConstants.END_ELEMENT:
     96                 //将事件对象可以转换为元素节点对象
     97                 EndElement endElement = (EndElement) event;
     98                 System.out.println("</" + endElement.getName().getLocalPart() + ">");
     99 
    100                 break;
    101             case XMLStreamConstants.END_DOCUMENT:
    102                 System.out.println("end docmuent");
    103                 break;
    104             default:
    105                 break;
    106             }
    107         }
    108     }
    109     
    110     /**
    111      * 基于指针的API输出流——XMLStreamWriter
    112      * @throws Exception
    113      */
    114     @Test
    115     public void testCreateByCursor() throws Exception{
    116         //创建输出流对象工厂
    117         XMLOutputFactory factory = XMLOutputFactory.newInstance();
    118         //创建输出流对象
    119         XMLStreamWriter streamWriter = factory.createXMLStreamWriter(System.out);
    120         //创建xml文档,根据对象方法创建对象元素
    121         streamWriter.writeStartDocument();
    122         //book start
    123         streamWriter.writeStartElement("book");
    124         streamWriter.writeAttribute("category", "CODING");
    125         
    126         streamWriter.writeStartElement("title");
    127         streamWriter.writeCharacters("Java Coding");
    128         streamWriter.writeEndElement();
    129         
    130         streamWriter.writeStartElement("author");
    131         streamWriter.writeCharacters("lisa");
    132         streamWriter.writeEndElement();
    133         
    134         streamWriter.writeStartElement("year");
    135         streamWriter.writeCharacters("2013");
    136         streamWriter.writeEndElement();
    137         
    138         streamWriter.writeStartElement("price");
    139         streamWriter.writeCharacters("79.9");
    140         streamWriter.writeEndElement();
    141         
    142         //book end
    143         streamWriter.writeEndElement();
    144         
    145         streamWriter.writeEndDocument();
    146         streamWriter.flush();
    147     }
    148     
    149     /**
    150      * 基于迭代器的API输出流——XMLEventWriter
    151      * @throws Exception
    152      */
    153     @Test
    154     public void testCreateByIterator() throws Exception{
    155         //创建输出流对象工厂
    156         XMLOutputFactory factory = XMLOutputFactory.newInstance();
    157         //创建输出流对象
    158         XMLEventWriter eventWriter = factory.createXMLEventWriter(System.out);
    159         //创建xml文档,根据对象方法创建对象元素
    160         eventWriter.add(new StartDocumentEvent());
    161         eventWriter.add(new StartElementEvent(new QName("book")));
    162         
    163         eventWriter.add(new StartElementEvent(new QName("title")));
    164         eventWriter.add(new CharacterEvent("Java Coding"));
    165         eventWriter.add(new EndElementEvent(new QName("title")));
    166         
    167         eventWriter.add(new StartElementEvent(new QName("author")));
    168         eventWriter.add(new CharacterEvent("rilay"));
    169         eventWriter.add(new EndElementEvent(new QName("author")));
    170         
    171         eventWriter.add(new StartElementEvent(new QName("year")));
    172         eventWriter.add(new CharacterEvent("2008"));
    173         eventWriter.add(new EndElementEvent(new QName("year")));
    174         
    175         eventWriter.add(new StartElementEvent(new QName("price")));
    176         eventWriter.add(new CharacterEvent("29.9"));
    177         eventWriter.add(new EndElementEvent(new QName("price")));
    178         
    179         eventWriter.add(new EndElementEvent(new QName("book")));
    180         eventWriter.add(new EndDocumentEvent());
    181         eventWriter.flush();
    182     }
    183     
    184 }
  • 相关阅读:
    (七)策略模式详解
    (六)观察者模式详解(包含观察者模式JDK的漏洞以及事件驱动模型)
    递归锁,死锁,使用递归锁解决死锁,信号量
    并发编程中的GIL锁(全局解释器锁)自己理解的他为啥存在
    线程了解以及创建线程的Threading模块中的部分方法
    进程 >> 互斥锁、队列与管道、生产者消费者模型
    进程比较基础的内容
    基于UDP协议的socket套接字编程 基于socketserver实现并发的socket编程
    网络基础 + 简易服务端和客户端
    单例模式
  • 原文地址:https://www.cnblogs.com/techlogy/p/5965104.html
Copyright © 2020-2023  润新知