首页 > 代码库 > XML编程总结(五)——使用StAX接口操作xml

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 =http://www.mamicode.com/ (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输出流——XMLStreamWriter112      * @throws Exception113      */114     @Test115     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 start123         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 end143         streamWriter.writeEndElement();144         145         streamWriter.writeEndDocument();146         streamWriter.flush();147     }148     149     /**150      * 基于迭代器的API输出流——XMLEventWriter151      * @throws Exception152      */153     @Test154     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 }

 

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