- 浏览: 79799 次
- 性别:
- 来自: 江西
最新评论
-
115646002:
我请问个问题:
我在配置eclipse3.6的时候,应该是某一 ...
eclipse 3.6 Helios 最新插件 -
xangqun:
是啊,不过真的很好用
tomcat插件与Jrebel插件整合(java web开发利器) -
freecode:
jrebel收费吧
tomcat插件与Jrebel插件整合(java web开发利器) -
lydawen:
开发js相当不错的插件 aptana - http://upd ...
eclipse3.5 Galileo最新实用插件 -
hszhl:
eclipse{wtp+cdt+ve#/windowBuild ...
eclipse3.5 Galileo最新实用插件
本文转载自http://zangweiren.iteye.com
野马(Mustang,Java 6.0代号)相比老虎(Tiger,Java 5.0代号)来说,从性能的提升、脚本语言(Javascript、JRuby、Groovy)的支持、对java.io.File的扩展到桌面应用的增强等各个方面,本领着实大了不少。
Java 6.0对XML支持的新特性有许多方面。比如StAX、针对XML-Web服务的Java架构(JAX-WS)2.0、针对XML绑定的API(JAXB)2.0、XML数字签名API,甚至还支持SQL:2003 'XML'数据类型。在这一篇文章中我们将要介绍的是StAX技术,因为它在我们的开发中将被使用地更加频繁。
StAX是Streaming API for XML的缩写,是一种针对XML的流式拉分析API。关于对XML进行分析(或解析)的技术,大家一定都不陌生了。在Java 6.0之前,就已经有四种:
- DOM:Document Object Model
- SAX:Simple API for XML
- JDOM:Java-based Document Object Model
- DOM4J:Document Object Model for Java
关于它们的解析原理,以及性能和优缺点,我会在本文的结尾做一个简要的介绍。这篇文章中,我们主要说说StAX这种新的解析方式。
首先我们来搞清楚两个概念:推分析和拉分析。
在程序中访问和操作XML文件一般有两种模型:DOM(文档对象模型)和流模型。它们的优缺点如下:
DOM缺点:需要一次性加载整个文档到内存中,对于大型文档,会造成性能问题。
流模型缺点:是只读的,并且只能向前,不能在文档中执行向后导航操作。
关于什么是DOM,文章结尾处会有介绍。这里我们简单说一下流:它是一个连续的字节序列,可以理解为不停地从源头向目标搬运着字节的特殊对象。
让我们回到主题。流模型每次迭代XML文档中的一个节点,适合于处理较大的文档,所耗内存空间小。它有两种变体--“推”模型和“拉”模型。
到此,我们就弄明白了“推分析”和“拉分析”的概念:
StAX就是一种拉分析式的XML解析技术。它也支持对XML文件的生成操作,但是这篇文章里我们只介绍有关解析的知识。
从一开始,JAXP(Java API for XML Processing)就提供了两种方法来处理XML:DOM和SAX。StAX是一种面向流的新方法,最终版本于2004年3月发布,并成为JAXP 1.4(包含在Java 6.0中)的一部分。StAX的实现使用了JWSDP(Java Web Services Development Pack)1.6,并结合了SJSXP(Sun Java System XML Streaming Parser,位于javax.xml.stream.*包中)。
JWSDP是用来开发Web Services、Web应用程序以及Java应用(主要是XML处理)的开发包。它包含的Java API有:
- JAXP:Java API for XML Processing
- JAXB:Java Architecture for XML Binding
- JAX-RPC:Java API for XML-based Remote Procedure Calls
- JAX-WS:Java API for XML Web Services
- SAAJ:SOAP with Attachments API for Java
- JAXR:Java API for XML Registries
- Web Services Registry
JWSDP的早期版本中还包括:
- Java Servlet
- JSP:JavaServer Pages
- JSF:JavaServer Faces
现在,JWSDP已经被GlassFish所替代。
StAX包括两套处理XML的API,分别提供了不同程度的抽象。它们是:基于指针的API和基于迭代器的API。
我们先来了解基于指针的API。它把XML作为一个标记(或事件)流来处理,应用程序可以检查解析器的状态,获得解析的上一个标记的信息,然后再处理下一个标记,依次类推。
在开始API探索之前,我们首先创建一个名为users.xml的XML文档用于测试,它的内容如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <company>
- <depart title="Develop Group">
- <user name="Tom" age="28" gender="male" >Manager</user>
- <user name="Lily" age="26" gender="female" />
- </depart>
- <depart title="Test Group">
- <user name="Frank" age="32" gender="male" >Team Leader</user>
- <user name="Bob" age="45" gender="male" />
- <user name="Kate" age="25" gender="female" />
- </depart>
- </company>
<?xml version="1.0" encoding="UTF-8"?> <company> <depart title="Develop Group"> <user name="Tom" age="28" gender="male" >Manager</user> <user name="Lily" age="26" gender="female" /> </depart> <depart title="Test Group"> <user name="Frank" age="32" gender="male" >Team Leader</user> <user name="Bob" age="45" gender="male" /> <user name="Kate" age="25" gender="female" /> </depart> </company>
可以让我们使用基于指针的API的接口是javax.xml.stream.XMLStreamReader(很遗憾,你不能直接实例化它),要得到它的实例,我们需要借助于javax.xml.stream.XMLInputFactory类。根据JAXP的传统风格,这里使用了抽象工厂(Abstract Factory)模式。如果你对这个模式很熟悉的话,就能够在脑海中想象出我们将要编写的代码的大致框架了。
首先,获得一个XMLInputFactory的实例。方法是:
XMLInputFactory factory = XMLInputFactory.newInstance();
或者:
XMLInputFactory factory = XMLInputFactory.newFactory();
这两个方法是等价的,它们都是创建了一个新的实例,甚至实例的类型都是完全一致的。因为它们的内部实现都是:
- {
- return (XMLInputFactory) FactoryFinder.find("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl");
- }
{ return (XMLInputFactory) FactoryFinder.find("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl"); }
接下来我们就可以创建XMLStreamReader实例了。我们有这样一组方法可以选择:
- XMLStreamReader createXMLStreamReader(java.io.Reader reader) throws XMLStreamException;
- XMLStreamReader createXMLStreamReader(javax.xml.tranform.Source source) throws XMLStreamException;
- XMLStreamReader createXMLStreamReader(java.io.InputStream stream) throws XMLStreamException;
- XMLStreamReader createXMLStreamReader(java.io.InputStream stream, String encoding) throws XMLStreamException;
- XMLStreamReader createXMLStreamReader(String systemId, java.io.InputStream stream) throws XMLStreamException;
- XMLStreamReader createXMLStreamReader(String systemId, java.io.Reader reader) throws XMLStreamException;
XMLStreamReader createXMLStreamReader(java.io.Reader reader) throws XMLStreamException; XMLStreamReader createXMLStreamReader(javax.xml.tranform.Source source) throws XMLStreamException; XMLStreamReader createXMLStreamReader(java.io.InputStream stream) throws XMLStreamException; XMLStreamReader createXMLStreamReader(java.io.InputStream stream, String encoding) throws XMLStreamException; XMLStreamReader createXMLStreamReader(String systemId, java.io.InputStream stream) throws XMLStreamException; XMLStreamReader createXMLStreamReader(String systemId, java.io.Reader reader) throws XMLStreamException;
这些方法都会根据给定的流创建一个XMLStreamReader实例,大家可以依据流的类型、是否需要指定解析XML的编码或者systemId来选择相应的方法。
在这里,我们对systemId稍作说明,并简单解释一下它与publicId的区别。
systemId和publicId是XML文档里DOCTYPE元素中经常出现的两个属性。它们都是对外部资源的引用,用以指明引用资源的地址。systemId是直接引用资源,publicId是间接定位外部资源。具体一点说是这样:
好了,我们接着用以上列出的第一个接口来创建一个XMLStreamReader实例:
- try {
- XMLStreamReader reader = factory.createXMLStreamReader(new FileReader("users.xml"));
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (XMLStreamException e) {
- e.printStackTrace();
- }
try { XMLStreamReader reader = factory.createXMLStreamReader(new FileReader("users.xml")); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (XMLStreamException e) { e.printStackTrace(); }
要遍历XML文档,需要用到XMLStreamReader的下面几个方法:
- int getEventType();
- boolean hasNext() throws XMLStreamException;
- int next() throws XMLStreamException;
int getEventType(); boolean hasNext() throws XMLStreamException; int next() throws XMLStreamException;
getEventType()方法返回XMLStreamConstants接口中定义的一个标记常量,表示当前指针所指向标记(或事件)的类型。根据当前事件类型的不同,应用程序可以做出不同的处理。标记常量的类型和含义如下:
- START_DOCUMENT:文档的开始
- END_DOCUMENT:文档的结尾
- START_ELEMENT:元素的开始
- END_ELEMENT:元素的结尾
- PROCESSING_INSTRUCTION:处理指令
- CHARACTERS:字符(文本或空格)
- COMMENT:注释
- SPACE:可忽略的空格
- ENTITY_REFERENCE:实体的引用
- ATTRIBUTE:元素的属性
- DTD:DTD
- CDATA:CDATA块
- NAMESPACE:命名空间的声明
- NOTATION_DECLARATION:标记的声明
- ENTITY_DECLARATION:实体的声明
next()方法将指针移动到下一个标记,它同时返回这个标记(或事件)的类型。此时若接着调用getEventType()方法则返回相同的值。
hasNext()用于判断是否还有下一个标记。只有当它返回true时才可以调用next()以及其它移动指针的方法。
看了上面几个方法的介绍,大家就会发现使用XMLStreamReader遍历XML文档是非常容易的,因为它的用法和每个人都熟悉的Java迭代器(Iterator)是一样的。下面我们就用已经掌握的这几个方法对上文中给出的XML文档做一个测试。希望你还记得它的内容,如果忘记了,请翻回去重新浏览一下。
我们的测试代码如下:
- /**
- * 列出所有用户
- *
- * @author zangweiren 2010-4-17
- *
- */
- public class ListUsers {
- // 获得解析器
- public static XMLStreamReader getStreamReader() {
- String xmlFile = ListUsers.class.getResource("/").getFile()
- + "users.xml";
- XMLInputFactory factory = XMLInputFactory.newFactory();
- try {
- XMLStreamReader reader = factory
- .createXMLStreamReader(new FileReader(xmlFile));
- return reader;
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (XMLStreamException e) {
- e.printStackTrace();
- }
- return null;
- }
- // 列出所有用户名称
- public static void listNames() {
- XMLStreamReader reader = ListUsers.getStreamReader();
- // 遍历XML文档
- try {
- while (reader.hasNext()) {
- int event = reader.next();
- // 如果是元素的开始
- if (event == XMLStreamConstants.START_ELEMENT) {
- // 列出所有用户名称
- if ("user".equalsIgnoreCase(reader.getLocalName())) {
- System.out.println("Name:"
- + reader.getAttributeValue(null, "name"));
- }
- }
- }
- reader.close();
- } catch (XMLStreamException e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- ListUsers.listNames();
- }
- }
/** * 列出所有用户 * * @author zangweiren 2010-4-17 * */ public class ListUsers { // 获得解析器 public static XMLStreamReader getStreamReader() { String xmlFile = ListUsers.class.getResource("/").getFile() + "users.xml"; XMLInputFactory factory = XMLInputFactory.newFactory(); try { XMLStreamReader reader = factory .createXMLStreamReader(new FileReader(xmlFile)); return reader; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (XMLStreamException e) { e.printStackTrace(); } return null; } // 列出所有用户名称 public static void listNames() { XMLStreamReader reader = ListUsers.getStreamReader(); // 遍历XML文档 try { while (reader.hasNext()) { int event = reader.next(); // 如果是元素的开始 if (event == XMLStreamConstants.START_ELEMENT) { // 列出所有用户名称 if ("user".equalsIgnoreCase(reader.getLocalName())) { System.out.println("Name:" + reader.getAttributeValue(null, "name")); } } } reader.close(); } catch (XMLStreamException e) { e.printStackTrace(); } } public static void main(String[] args) { ListUsers.listNames(); } }
运行结果:
Name:Lily
Name:Frank
Name:Bob
Name:Kate
在上面的示例代码中,我们用到了XMLStreamReader的两个新方法:
String getLocalName(); String getAttributeValue(String namespaceURI, String localName);
与此相关的还有一个方法:
QName getName();
这三个方法牵扯到XML的namespace(命名空间)、localName(本地名称)、QName(Qualified Name,限定名称)三个概念,我们顺便解释一下:
命名空间是为了支持相同名称不同含义的XML标签而产生的,它可以这么定义:
- <com:company xmlns:com="http://www.zangweiren.com/company">
- <!-- here is other tags -->
- </com:company>
<com:company xmlns:com="http://www.zangweiren.com/company"> <!-- here is other tags --> </com:company>
其中,com是命名空间的前缀,company是命名空间的标签,http://www.zangweiren.com/company是命名空间的标识,相同的标识被认为是同一个命名空间。标识又叫URI,是唯一的,有URL(统一资源定位器)和URN(统一资源名称)两种。前缀是命名空间的简写,目的是为了使用方便。命名空间被声明后就可以被使用:
- <com:company xmlns:com="http://www.zangweiren.com/company">
- <com:depart name="Develop Group" />
- </com:company>
<com:company xmlns:com="http://www.zangweiren.com/company"> <com:depart name="Develop Group" /> </com:company>
在上例的<com:depart />标签中,前缀com是命名空间,depart是localName,这两个合起来就是QName。
在明白了这三个XML基本概念之后,也就明白了getLocalName()和getAttributeValue(String namespaceURI, String localName)方法的含义。
现在,我们已经学会了使用XMLStreamReader遍历XML文档,并对特定标签进行解析了。
我们再来看看下面两个方法:
String getElementText() throws XMLStreamException; int nextTag() throws XMLStreamException;
getElementText()方法返回元素的开始标签(START_ELEMENT)和关闭标签(END_ELEMENT)之间的所有文本内容,若遇到嵌套的元素就会抛出异常。
nextTag()方法将跳过所有空白、注释或处理指令,直到遇到START_ELEMENT或END_ELEMENT。它在解析只含元素内容的XML文档时很有用。否则,在发现标记之前遇到非空白文本(不包括注释和处理指令),就会抛出异常。
比如我们修改上一个测试程序,增加一个新方法:
- // 列出所有用户的名称和年龄
- public static void listNamesAndAges() {
- XMLStreamReader reader = ListUsers.getStreamReader();
- try {
- while (reader.hasNext()) {
- // 跳过所有空白、注释或处理指令,到下一个START_ELEMENT
- int event = reader.nextTag();
- if (event == XMLStreamConstants.START_ELEMENT) {
- if ("user".equalsIgnoreCase(reader.getLocalName())) {
- System.out.println("Name:"
- + reader.getAttributeValue(null, "name")
- + ";Age:"
- + reader.getAttributeValue(null, "age"));
- }
- }
- }
- reader.close();
- } catch (XMLStreamException e) {
- e.printStackTrace();
- }
- }
// 列出所有用户的名称和年龄 public static void listNamesAndAges() { XMLStreamReader reader = ListUsers.getStreamReader(); try { while (reader.hasNext()) { // 跳过所有空白、注释或处理指令,到下一个START_ELEMENT int event = reader.nextTag(); if (event == XMLStreamConstants.START_ELEMENT) { if ("user".equalsIgnoreCase(reader.getLocalName())) { System.out.println("Name:" + reader.getAttributeValue(null, "name") + ";Age:" + reader.getAttributeValue(null, "age")); } } } reader.close(); } catch (XMLStreamException e) { e.printStackTrace(); } }
然后把它添加到主方法中:
- public static void main(String[] args) {
- ListUsers.listNames();
- ListUsers.listNamesAndAges();
- }
public static void main(String[] args) { ListUsers.listNames(); ListUsers.listNamesAndAges(); }
运行它试试看,在解析到<user name="Tom" age="28" gender="male" >Manager</user>的时候会报错,因此你会得到一个类似这样的错误信息:
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[4,53]
Message: found: CHARACTERS, expected START_ELEMENT or END_ELEMENT
对于基于指针的XMLStreamReader来说,虽然API文档说的是“事件”,但是我们把它看成“标记”更易于理解,而且不会与另一套基于事件的API相混淆。
XMLStreamReader的某些方法,无论当前标记(或事件)是什么类型的,都可以被调用。它们的定义和作用如下:
- String getVersion();//获得XML文档中的版本信息
- String getEncoding();//获得XML文档中的指定编码
- javax.xml.namespace.NamespaceContext getNamespaceContext();//获得当前有效的命名空间上下文,包含前缀、URI等信息
- String getNamespaceURI();//获得当前有效的命名空间的URI
- javax.xml.stream.Location getLocation();//获得当前标记的位置信息,包含行号、列号等
- boolean hasName();//判断当前标记是否有名称,比如元素或属性
- boolean hasText();//判断当前标记是否有文本,比如注释、字符或CDATA
- boolean isStartElement();//判断当前标记是否是标签开始
- boolean isEndElement();//判断当前标记是否是标签结尾
- boolean isCharacters();//判断当前标记是否是字符
- boolean isWhiteSpace();//判断当前标记是否是空白
对于以上方法都很容易理解和记忆,我们不再编写代码展示它们的效果。
让我们看看有关属性操作方法。还是首先熟悉一下它们的定义:
- int getAttributeCount();
- String getAttributeLocalName(int index);
- QName getAttributeName(int index);
- String getAttributeNamespace(int index);
- String getAttributePrefix(int index);
- String getAttributeType(int index);
- String getAttributeValue(int index);
- String getAttributeValue(String namespaceURI, String localName);
int getAttributeCount(); String getAttributeLocalName(int index); QName getAttributeName(int index); String getAttributeNamespace(int index); String getAttributePrefix(int index); String getAttributeType(int index); String getAttributeValue(int index); String getAttributeValue(String namespaceURI, String localName);
这些方法都十分容易理解,基本上看方法的名称和参数就知道它的用途了。而且最后一个方法在上面的示例中我们已经用过了。让我们再用一个简单的示例程序进一步加深对这些方法的认识。
- // 列出所有用户的名称和年龄
- public static void listNamesAndAges() {
- XMLStreamReader reader = ListUsers.getStreamReader();
- try {
- while (reader.hasNext()) {
- // 跳过所有空白、注释或处理指令,到下一个START_ELEMENT
- int event = reader.nextTag();
- if (event == XMLStreamConstants.START_ELEMENT) {
- if ("user".equalsIgnoreCase(reader.getLocalName())) {
- System.out.println("Name:"
- + reader.getAttributeValue(null, "name")
- + ";Age:"
- + reader.getAttributeValue(null, "age"));
- }
- }
- }
- reader.close();
- } catch (XMLStreamException e) {
- e.printStackTrace();
- }
- }
// 列出所有用户的名称和年龄 public static void listNamesAndAges() { XMLStreamReader reader = ListUsers.getStreamReader(); try { while (reader.hasNext()) { // 跳过所有空白、注释或处理指令,到下一个START_ELEMENT int event = reader.nextTag(); if (event == XMLStreamConstants.START_ELEMENT) { if ("user".equalsIgnoreCase(reader.getLocalName())) { System.out.println("Name:" + reader.getAttributeValue(null, "name") + ";Age:" + reader.getAttributeValue(null, "age")); } } } reader.close(); } catch (XMLStreamException e) { e.printStackTrace(); } }
把它加入到主方法中:
- public static void main(String[] args) {
- ListUsers.listNames();
- // ListUsers.listNamesAndAges();
- ListUsers.listAllAttrs();
- }
public static void main(String[] args) { ListUsers.listNames(); // ListUsers.listNamesAndAges(); ListUsers.listAllAttrs(); }
运行结果:
2.name=Lily;age=26;gender=female;
3.name=Frank;age=32;gender=male;
4.name=Bob;age=45;gender=male;
5.name=Kate;age=25;gender=female;
相信你看到这里,已经可以顺利地使用XMLStreamReader来完成XML文档的解析了。
上面我们介绍了基于指针的StAX API。这种方式尽管效率高,但是没有提供XML结构的抽象,因此是一种低层API。
较为高级的基于迭代器的API允许应用程序把XML作为一系列事件对象来处理,每个对象和应用程序交换XML结构的一部分。应用程序只需要确定解析事件的类型,将其转换成对应的具体类型,然后利用其方法获得属于该事件对象的信息。
StAX中基于迭代器的API是一种面向对象的方式,这也是它与基于指针的API的最大区别。它通过将事件转变为对象,让应用程序可以用面向对象的方式处理它们,这有利于模块化和不同组件之间的代码重用。
事件迭代器API的主要接口是javax.xml.stream.XMLEventReader和javax.xml.stream.events.XMLEvent。XMLEventReader和XMLStreamReader相比要简单的多,这是因为关于解析事件的所有信息都封装在了事件对象(XMLEvent)中。
创建XMLEvent对象前同样需要一个XMLInputFactory实例。它有如下这些创建XMLEvent实例的方法:
- XMLEventReader createXMLEventReader(java.io.InputStream stream) throws XMLStreamException;
- XMLEventReader createXMLEventReader(java.io.InputStream stream, String encoding) throws XMLStreamException;
- XMLEventReader createXMLEventReader(java.io.Reader reader) throws XMLStreamException;
- XMLEventReader createXMLEventReader(String systemId, java.io.InputStream stream) throws XMLStreamException;
- XMLEventReader createXMLEventReader(String systemId, java.io.Reader reader) throws XMLStreamException;
- XMLEventReader createXMLEventReader(Source source) throws XMLStreamException;
- XMLEventReader createXMLEventReader(XMLStreamReader reader) throws XMLStreamException;
XMLEventReader createXMLEventReader(java.io.InputStream stream) throws XMLStreamException; XMLEventReader createXMLEventReader(java.io.InputStream stream, String encoding) throws XMLStreamException; XMLEventReader createXMLEventReader(java.io.Reader reader) throws XMLStreamException; XMLEventReader createXMLEventReader(String systemId, java.io.InputStream stream) throws XMLStreamException; XMLEventReader createXMLEventReader(String systemId, java.io.Reader reader) throws XMLStreamException; XMLEventReader createXMLEventReader(Source source) throws XMLStreamException; XMLEventReader createXMLEventReader(XMLStreamReader reader) throws XMLStreamException;
最后一个方法不同与其它的,它是将一个XMLStreamReader对象转换成一个XMLEventReader对象。值得注意的是,XMLInputFactory没有提供将XMLEventreader对象转换成XMLStreamreader对象的方法。我想,在我们的开发过程中,应该不会出现这种需要将高层API转换成低层API来使用的情况。
XMLEventReader接口扩展了java.util.Iterator接口,它定义了以下几个方法:
- String getElementText() throws XMLStreamException;
- boolean hasNext();
- XMLEvent nextEvent() throws XMLStreamException;
- XMLEvent nextTag() throws XMLStreamException;
- XMLEvent peek() throws XMLStreamException;
String getElementText() throws XMLStreamException; boolean hasNext(); XMLEvent nextEvent() throws XMLStreamException; XMLEvent nextTag() throws XMLStreamException; XMLEvent peek() throws XMLStreamException;
其中,getElementText()、hasNext()、nextTag()三个方法的含义及用法类似于XMLStreamReader,而nextEvent()方法类似于XMLStreamReader的next()方法。所以,这里只对peed()方法做一下说明。
调用peek()方法,你将得到下一个事件对象。它与nextEvent()方法的不同是,当你连续两次或两次以上调用它时,你得到的都是同一个事件对象。
我们再看看XMLEvent接口中定义的方法。这些方法大体可以分为三种类别。第一类是用于事件类型判断的:
- boolean isAttribute();//判断该事件对象是否是元素的属性
- boolean isCharacters();//判断该事件对象是否是字符
- boolean isStartDocument();//判断该事件对象是否是文档开始
- boolean isEndDocument();//判断该事件对象是否是文档结尾
- boolean isStartElement();//判断该事件对象是否是元素开始
- boolean isEndElement();//判断该事件对象是否是元素结尾
- boolean isEntityReference();//判断该事件对象是否是实体的引用
- boolean isNamespace();//判断该事件对象是否是命名空间
- boolean isProcessingInstruction();//判断该事件对象是否是处理指令
第二类是将XMLEvent转换为具体的子类对象的:
- Characters asCharacters();//转换为字符事件对象
- StartElement asStartElement();//转换为标签开始事件对象
- EndElement asEndElement();//转换为标签结尾事件对象
第三类是获取事件对象通用信息的:
- javax.xml.stream.Location getLocation();//获得事件对象的位置信息,类似于XMLStreamReader的getLocation()方法
- int getEventType();//获得事件对象的类型,类似于XMLStreamReader的getEventType()方法
其中,getEventType()方法的返回值也是XMLStreamConstants中定义的常量,其类型和含义与XMLStreamReader的getEventType()方法的返回值完全相同。
下面让我们用一段示例代码来熟悉基于迭代器的StAX API的使用方法,进而引出XMLEvent接口的子接口类型。我们仍然使用users.xml作为测试文件:
- // 列出所有信息
- @SuppressWarnings("unchecked")
- public static void listAllByXMLEventReader() {
- String xmlFile = ListUsers.class.getResource("/").getFile()
- + "users.xml";
- XMLInputFactory factory = XMLInputFactory.newInstance();
- try {
- // 创建基于迭代器的事件读取器对象
- XMLEventReader reader = factory
- .createXMLEventReader(new FileReader(xmlFile));
- // 遍历XML文档
- while (reader.hasNext()) {
- XMLEvent event = reader.nextEvent();
相关推荐
【最新编排】全面解析JAVA XML分析技术
java在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava在线解析xmljava...
java http 发送xml报文(java发送xml报文实例+参数)java http 发送xml报文java http 发送xml报文(java发送xml报文实例+参数)
Java中四种XML解析技术 Java XML解析技术
JAVA 解析XML和生成XML文档源码。比较全 1.DOM生成和解析XML文档 2.SAX生成和解析XML文档 3.DOM4J生成和解析XML文档 4.JDOM生成和解析XML
JAVA XML 數據.docJAVA XML 數據.doc JAVA XML 數據.doc JAVA XML 數據.doc
java xml 编程技术资料 ,系统介绍 java 如何开发xml,
java http 发送xml报文java http 发送xml报文java http 发送xml报文java http 发送xml报文java http 发送xml报文java http 发送xml报文java http 发送xml报文java http 发送xml报文java http 发送xml报文java http ...
Java XML编程指南 Java XML编程指南 Java XML编程指南
这是一个java对xml操作的两个类,xml文件的节点都是已知的,都需要提前指定.
java xml编程指南
主要针对Ajax和Flash应用程序 无论您现在正在还是将来会进行Java程序的开发并且需要用到XML,或者您正在参与新的点对点技术、消息技术以及Web service技术的相关应用或者开发,《Java与XML》(第三版)都是一本不...
java xml.java操作XML文档,简单易用,快速生成
Java实现XML文档到word文档转换
java XML解析方式实现自动生成word文档,文档中主要描述word模板的使用方法,文件中带有案例代码,可以方便理解
使用dom4j封装的工具类,可以实现 xml to map ,map to xml 互相转换,带属性 不带属性,有根节点 和无根节点都可以转换,具体看测试代码
Java绑定XML架构的技术内涵,可以看看,了解一下
Java 解析XML性能分析Demo。包含了DOM解析,SAX解析, JDOM解析,DOM4J解析,JAXB解析例子。