使用StAX事件定义解析大XML

首先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-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工程代码

 

你可能感兴趣的:(apache,maven,xml,JSF,IBM)