首先StAX的普及知识可以参考一下IBM Developement的下面这个系列文章
同时参考了如下文章, 并作了简化
先简单的讲一下我个人的基本思路
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工程代码