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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

 

以上是关于XML编程总结——使用StAX接口操作xml的主要内容,如果未能解决你的问题,请参考以下文章

XML编程总结——使用DOM接口操作xml

XML编程总结——使用SAX接口操作xml

使用 StAx 解析 XML 文件时出错

JAXPDOMSAXSTAX

XML编程总结——使用dom4j方式操作xml

XML编程知识点总结