首先StAX的普及知识可以参考一下IBM Developement的下面这个系列文章
http://www.ibm.com/developerworks/cn/xml/x-stax1.html
http://www.ibm.com/developerworks/cn/xml/x-stax2.html
http://www.ibm.com/developerworks/cn/xml/x-stax3.html
http://www.ibm.com/developerworks/cn/xml/x-stax2.html
http://www.ibm.com/developerworks/cn/xml/x-stax3.html
同时参考了如下文章, 并作了简化
http://www.ibm.com/developerworks/cn/xml/x-1001mace/
先简单的讲一下我个人的基本思路
1. 采用流方式读取指定的节点
2. 转换成Node节点方式
3. 采用XPath, JAXB, 简单的Node处理等方式处理
我们采用maven的POM.xml作为例子,我们要解析
<dependency> <groupId>javax.faces</groupId> <artifactId>jsf-api</artifactId> <version>1.2</version> <scope>runtime</scope> </dependency>
1. 自定义Dependency事件
public class DependencyEvent implements XMLEvent {
public static final int DEPENDENCY_EVENT = 10000; // 定义事件枚举值, 0~255被StAX占用不要使用
......(省略其他属性定义)
private Node node;// 事件生成的Node节点
private List<XMLEvent> eventList;// 自定义的时间列表集合
// 构建函数
public DependencyEvent(List<XMLEvent> eventList) {
this.eventList = eventList;
}
// 生成自定义事件的Node节点
public Node getNode() throws XMLStreamException {
if (node == null) {
DOMResult result = new DOMResult(DOMUtils.getInstance()
.getBuilder().newDocument().createDocumentFragment());
XMLEventWriter writer = StAXUtils.getInstance().getOutputFactory()
.createXMLEventWriter(result);
for (XMLEvent event : eventList) {
writer.add(event);
}
writer.close();
node = result.getNode().getFirstChild();
}
return node;
}
...... (省略其他方法)
}
2. 自定义事件的Reader, 由于我们自定义了事件,默认的StAX的Reader无法识别
// 这里选择继承EventReaderDelegate类来简化, 当然也可以选择实现EventReader接口
// 其中最关键的就是peek()方法, 在peek方法中,可以根据自己的需求封装自定义事件
public class DependencyEventReader extends EventReaderDelegate {
private XMLEvent nextEvent;
public DependencyEventReader(InputStream in) throws XMLStreamException {
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader streamReader = factory.createXMLStreamReader(in);
XMLEventReader eventReader = factory.createXMLEventReader(streamReader);
super.setParent(eventReader);
}
@Override
public Object next() {
try {
return nextEvent();
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
@Override
public XMLEvent nextEvent() throws XMLStreamException {
if (nextEvent == null) {
nextEvent = peek();
}
XMLEvent result = nextEvent;
nextEvent = null;
return result;
}
@Override
public XMLEvent peek() throws XMLStreamException {
if (nextEvent == null && getParent().hasNext()) {
nextEvent = getParent().nextEvent();
if (nextEvent.isStartElement()) {
List<XMLEvent> eventList = new ArrayList<XMLEvent>();
QName qName = nextEvent.asStartElement().getName();
eventList.add(nextEvent);
if (qName.getLocalPart().equals("dependency")) {
int level = 1;
while (getParent().hasNext()) {
XMLEvent event = getParent().nextEvent();
eventList.add(event);
if (event.isStartElement()) {
level++;
} else if (event.isEndElement()) {
level--;
if (level == 0) {
break;
}
}
}
// 这个是关键, 生成自定义事件
nextEvent = new DependencyEvent(eventList);
}
}
}
return nextEvent;
}
}
3. 处理自定义节点,本例中采用了JAXB方法进行处理
Dependency模型, 这里简化了excludes等不定属性的处理
package demo;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "dependency", namespace = "http://maven.apache.org/POM/4.0.0")
public class Dependency {
@XmlElement(namespace = "http://maven.apache.org/POM/4.0.0")
private String groupId;
@XmlElement(namespace = "http://maven.apache.org/POM/4.0.0")
private String artifactId;
@XmlElement(namespace = "http://maven.apache.org/POM/4.0.0")
private String version;
@XmlElement(namespace = "http://maven.apache.org/POM/4.0.0")
private String scope;
......(省略getter/setter)
}
自定义事件的处理
public class DependencyEvent implements XMLEvent {
public static final int DEPENDENCY_EVENT = 10000;
private Dependency dependency;
.......(省略)
public Dependency getDependency() throws JAXBException, XMLStreamException {
JAXBContext jc = JAXBContext.newInstance(Dependency.class);
Unmarshaller u = jc.createUnmarshaller();
dependency = (Dependency) u.unmarshal(getNode());
return dependency;
}
}
附上简单的eclipse工程代码