使用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获取。
测试代码:
public class StAXTest {
private InputStream is;
@Before
public void setUp() throws Exception{
is=StAXTest.class.getClassLoader()
.getResourceAsStream("books.xml");
}
/**
* 基于指针的方式读取xml文档——XMLStreamReader
* @throws Exception
*/
@Test
public void testRetrieveByCursor() throws Exception{
//创建读取流工厂对象
XMLInputFactory factory = XMLInputFactory.newInstance();
//创建基于指针的读取流对象
XMLStreamReader streamReader = factory.createXMLStreamReader(is);
//用指针迭代
while(streamReader.hasNext()){
//事件的ID
int eventId=streamReader.next();
switch (eventId) {
case XMLStreamConstants.START_DOCUMENT:
System.out.println("start docmuent");
break;
case XMLStreamConstants.START_ELEMENT:
System.out.println("<"+streamReader.getLocalName()+">");
for(int i=0;i<streamReader.getAttributeCount();i++){
System.out.println(streamReader.getAttributeLocalName(i)+
"="+streamReader.getAttributeValue(i));
}
break;
case XMLStreamConstants.CHARACTERS:
if(streamReader.isWhiteSpace()){
break;
}
System.out.println(streamReader.getText());
break;
case XMLStreamConstants.END_ELEMENT:
System.out.println("</"+streamReader.getLocalName()+">");
break;
case XMLStreamConstants.END_DOCUMENT:
System.out.println("end docmuent");
break;
default:
break;
}
}
}
/**
* 基于迭代器的方式读取xml文档——XMLEventReader
* @throws Exception
*/
@Test
public void testRetrieveByIterator() throws Exception{
//创建读取流工厂对象
XMLInputFactory factory = XMLInputFactory.newInstance();
//创建基于迭代器(事件流对象)的流对象
XMLEventReader eventReader = factory.createXMLEventReader(is);
//迭代xml文档
while (eventReader.hasNext()) {
//得到具体的 事件对象,就是引发事件的对象(可以是元素节点、文本节点、属性节点)
XMLEvent event = eventReader.nextEvent();
switch (event.getEventType()) {
case XMLStreamConstants.START_DOCUMENT:
System.out.println("start docmuent");
break;
case XMLStreamConstants.START_ELEMENT:
//将事件对象可以转换为元素节点对象
StartElement element = (StartElement) event;
System.out.println("<" + element.getName().getLocalPart() + ">");
for (Iterator it = element.getAttributes(); it.hasNext();) {
Attribute attr = (Attribute) it.next();
System.out.println(attr.getName().getLocalPart() + "=" + attr.getValue());
}
break;
case XMLStreamConstants.CHARACTERS:
//将事件对象可以转换成文本节点
Characters charData = (Characters) event;
if (charData.isIgnorableWhiteSpace() && charData.isWhiteSpace()) {
break;
}
System.out.println(charData.getData());
break;
case XMLStreamConstants.END_ELEMENT:
//将事件对象可以转换为元素节点对象
EndElement endElement = (EndElement) event;
System.out.println("</" + endElement.getName().getLocalPart() + ">");
break;
case XMLStreamConstants.END_DOCUMENT:
System.out.println("end docmuent");
break;
default:
break;
}
}
}
/**
* 基于指针的API输出流——XMLStreamWriter
* @throws Exception
*/
@Test
public void testCreateByCursor() throws Exception{
//创建输出流对象工厂
XMLOutputFactory factory = XMLOutputFactory.newInstance();
//创建输出流对象
XMLStreamWriter streamWriter = factory.createXMLStreamWriter(System.out);
//创建xml文档,根据对象方法创建对象元素
streamWriter.writeStartDocument();
//book start
streamWriter.writeStartElement("book");
streamWriter.writeAttribute("category", "CODING");
streamWriter.writeStartElement("title");
streamWriter.writeCharacters("Java Coding");
streamWriter.writeEndElement();
streamWriter.writeStartElement("author");
streamWriter.writeCharacters("lisa");
streamWriter.writeEndElement();
streamWriter.writeStartElement("year");
streamWriter.writeCharacters("2013");
streamWriter.writeEndElement();
streamWriter.writeStartElement("price");
streamWriter.writeCharacters("79.9");
streamWriter.writeEndElement();
//book end
streamWriter.writeEndElement();
streamWriter.writeEndDocument();
streamWriter.flush();
}
/**
* 基于迭代器的API输出流——XMLEventWriter
* @throws Exception
*/
@Test
public void testCreateByIterator() throws Exception{
//创建输出流对象工厂
XMLOutputFactory factory = XMLOutputFactory.newInstance();
//创建输出流对象
XMLEventWriter eventWriter = factory.createXMLEventWriter(System.out);
//创建xml文档,根据对象方法创建对象元素
eventWriter.add(new StartDocumentEvent());
eventWriter.add(new StartElementEvent(new QName("book")));
eventWriter.add(new StartElementEvent(new QName("title")));
eventWriter.add(new CharacterEvent("Java Coding"));
eventWriter.add(new EndElementEvent(new QName("title")));
eventWriter.add(new StartElementEvent(new QName("author")));
eventWriter.add(new CharacterEvent("rilay"));
eventWriter.add(new EndElementEvent(new QName("author")));
eventWriter.add(new StartElementEvent(new QName("year")));
eventWriter.add(new CharacterEvent("2008"));
eventWriter.add(new EndElementEvent(new QName("year")));
eventWriter.add(new StartElementEvent(new QName("price")));
eventWriter.add(new CharacterEvent("29.9"));
eventWriter.add(new EndElementEvent(new QName("price")));
eventWriter.add(new EndElementEvent(new QName("book")));
eventWriter.add(new EndDocumentEvent());
eventWriter.flush();
}
}
StAX-api 1.0.jar下载路径: