首页 > 代码库 > 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