利用Stax处理xml文档
一、创建books.xml
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="神话小说">
<title lang="en">西游记</title>
<author>吴承恩</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="108英雄">
<title lang="en">水浒传</title>
<author>施耐庵</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="文学">
<title lang="en">资治通鉴</title>
<author>张三</author>
<author>李四</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>王五</author>
<year>2003</year>
<price>49.99</price>
</book>
<book category="历史">
<title lang="en">史记</title>
<author>司马迁</author>
<year>2003</year>
<price>39.95</price>
</book>
<book category="神话小说">
<title lang="en">封神榜</title>
<author>吴晓六</author>
<year>2005</year>
<price>30.00</price>
</book>
</bookstore>
二、写一个测试类,测试几种不同方式的读取解析xml;
主要有这几种方式:
1、基于光标的xml解析查找元素;
2、基于迭代模式查找;
3、使用过滤器的方式高效解析文档;(可以学习通过内部类的方式编写过滤器的设计模式);
4、通过XPath方式处理处理xml;
三、写文档和修改文档
1、 写文档和修改文档, 使用XMLStreamWriter创建一个xml;
2、使用Transformer修改xml中节点信息
package org.itat.stax;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.EventFilter;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.events.XMLEvent;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class TestStax {
/**
* 基于光标的xml解析查找元素
* xml流的常量
* XMLStreamConstants constant 英[ˈkɒnstənt] 常量
* START_ELEMENT=1
* END_ELEMENT=2
* CHARACTERS=4 characters英 ['kærɪktəz]字符
* PROCESSING_INSTRUCTION=3
*/
@Test
public void test01(){
XMLInputFactory factory = XMLInputFactory.newInstance();
InputStream is=null;
StringBuffer sb=new StringBuffer();
try {
//通过反射获取输入流
is= TestStax.class.getClassLoader().getResourceAsStream("books.xml");
XMLStreamReader reader=factory.createXMLStreamReader(is);
while(reader.hasNext()){//是否还有下一个元素
int type=reader.next();
sb.append(" "+((Integer)type).toString());
if(type==XMLStreamConstants.START_ELEMENT){
System.out.println(reader.getName());
}else if (type==XMLStreamConstants.CHARACTERS) {
System.out.println(reader.getText().trim());
}else if (type==XMLStreamConstants.END_ELEMENT) {
System.out.println("/"+reader.getName());
}
}
System.out.println(sb.toString());
} catch (XMLStreamException e) {
e.printStackTrace();
}finally{
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 获得标签的属性;
*/
@Test
public void test02(){
XMLInputFactory factory = XMLInputFactory.newInstance();
InputStream is=null;
try {
//通过反射获取输入流
is= TestStax.class.getClassLoader().getResourceAsStream("books.xml");
XMLStreamReader reader=factory.createXMLStreamReader(is);
while(reader.hasNext()){//是否还有下一个元素
int type=reader.next();
if(type==XMLStreamConstants.START_ELEMENT){
String name=reader.getName().toString();
if(name.equals("book")){
System.out.println(reader.getAttributeName(0)+":"+reader.getAttributeValue(0));
}
}
}
} catch (XMLStreamException e) {
e.printStackTrace();
}finally{
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void test03(){
XMLInputFactory factory=XMLInputFactory.newInstance();
InputStream is=null;
try {
//TestStax.class是获得这个类相对于Class类的对象。后面的方法是获得这个类对象的加载器。
is=TestStax.class.getClassLoader().getResourceAsStream("books.xml");
XMLStreamReader reader=factory.createXMLStreamReader(is);
while(reader.hasNext()){
int type=reader.next();
if(type==XMLStreamConstants.START_ELEMENT){
String name=reader.getName().toString();
if(name.equals("title")){
System.out.print(reader.getElementText()+":");
}
if(name.equals("price")){
System.out.print(reader.getElementText()+"\n");
}
}
}
} catch (XMLStreamException e) {
e.printStackTrace();
}finally{
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 通过XMLEventReader类
* 基于迭代模式查找
* @throws XMLStreamException
*/
@Test
public void test04() throws XMLStreamException{
XMLInputFactory factory=XMLInputFactory.newInstance();
InputStream is=null;
//TestStax.class是获得这个类相对于Class类的对象。后面的方法是获得这个类对象的加载器。
is=TestStax.class.getClassLoader().getResourceAsStream("books.xml");
//基于迭代模型的操作方式
XMLEventReader reader =factory.createXMLEventReader(is);
while(reader.hasNext()){
//通过XMLEvent来获取是否是某种节点类型
XMLEvent event=reader.nextEvent();
if(event.isStartElement()){
//通过event.asXXX转换节点
String name=event.asStartElement().getName().toString();
if(name.equals("title")){
System.out.print(reader.getElementText()+":");
}
if(name.endsWith("price")){
System.out.print(reader.getElementText()+"\n");
}
}
}
}
/**
* 使用过滤器的方式高效解析文档
* 通过匿名内部类来进行过滤
* @throws XMLStreamException
*/
@Test
public void test05() throws XMLStreamException{
XMLInputFactory factory=XMLInputFactory.newInstance();
InputStream is=null;
is=TestStax.class.getClassLoader().getResourceAsStream("books.xml");
//基于Filter的过滤方式,可以有效的过滤掉不用进行操作的节点,效率会高一些
XMLEventReader reader =factory.createFilteredReader(factory.createXMLEventReader(is),
new EventFilter() {
@Override
public boolean accept(XMLEvent event) {
// 返回true表示会显示,返回false表示不会显示
if(event.isStartElement()){
String name=event.asStartElement().getName().toString();
if(name.equals("title")||name.equals("price")) return true;
}
return false;
}
});
int num =0;
while(reader.hasNext()){
XMLEvent event=reader.nextEvent();
if(event.isStartElement()){
String name=event.asStartElement().getName().toString();
if(name.equals("title")){
System.out.print(reader.getElementText()+":");
}
if(name.endsWith("price")){
System.out.print(reader.getElementText()+"\n");
}
}
num++;
}
System.out.println(num);
}
/**
* 通过XPath方式处理处理xml
* 1、先创建文档对象
* 2、然后通过DocumentBuilder创建document的文档对象,
* 3、然后创建XPath对象
* 4、第1个参数就是xpath,第2个参数就是文档
* 5、遍历输出相应的结果。
* @throws XPathExpressionException
*/
@Test
public void test06() throws XPathExpressionException{
InputStream is=null;
try {
is=TestStax.class.getClassLoader().getResourceAsStream("books.xml");
//newInstance()获取 DocumentBuilderFactory 的新实例。newDocumentBuilder() 使用当前配置的参数创建一个新的 DocumentBuilder 实例。
DocumentBuilder db=DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document=db.parse(is);//parse(InputStream is) 将给定 InputStream 的内容解析为一个 XML 文档,并且返回一个新的 DOM Document 对象。
XPath xpath=XPathFactory.newInstance().newXPath();//newXPath() 返回使用实例化 XPathFactory 时确定的底层对象模型的新 XPath。
NodeList list=(NodeList)xpath.evaluate("//book[@category='神话小说']", document,XPathConstants.NODESET);//evaluate 英 [ɪˈvæljueɪt] vi. 评价,估价
for(int i=0;i<list.getLength();i++){
Element ele=(Element)list.item(i);
System.out.println(ele.getElementsByTagName("title").item(0).getTextContent());
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 写文档和修改文档
* 使用XMLStreamWriter创建一个xml
*/
@Test
public void test07(){
try {
System.out.println("---Demo:第一个(没有命名空间)--------------------");
XMLStreamWriter xsw=XMLOutputFactory.newInstance().createXMLStreamWriter(System.out);
xsw.writeStartDocument("UTF-8", "1.0");
xsw.writeEndDocument();
xsw.writeStartElement("people");
xsw.writeStartElement("id");
xsw.writeCharacters("1");
xsw.writeEndElement();
xsw.writeEndElement();
xsw.flush();//清空
xsw.close();//关闭
System.out.println();
System.out.println("---Demo:第二个(添加命名空间)--------------------");
XMLStreamWriter xsw2=XMLOutputFactory.newInstance().createXMLStreamWriter(System.out);
xsw2.writeStartDocument("UTF-8", "1.0");
xsw2.writeEndDocument();
String prefix="namespace_lizi";
String localName1="person";
String localName2="id";
String namespaceURI="ns";
xsw2.writeStartElement(prefix, localName1,namespaceURI);
xsw2.writeStartElement(namespaceURI, localName2);
xsw2.writeCharacters("1");
xsw2.writeEndElement();
xsw2.writeEndElement();
xsw2.flush();
xsw2.close();
} catch (XMLStreamException e) {
e.printStackTrace();
} catch (FactoryConfigurationError e) {
e.printStackTrace();
}
}
/**
* 使用Transformer修改xml中节点信息
*/
@Test
public void Test08(){
InputStream is=null;
try {
// 1、读取文件路径
is=TestStax.class.getClassLoader().getResourceAsStream("books.xml");
// 2、先创建文档处理对象
DocumentBuilder db=DocumentBuilderFactory.newInstance().newDocumentBuilder();
//3、通过文档处理对象,创建文档对象
Document document =db.parse(is);
// 4、创建XPath对象
XPath xpath =XPathFactory.newInstance().newXPath();
// 5、创建Transformer对象
Transformer transformer=TransformerFactory.newInstance().newTransformer();
// 6、设置输出属性的编码格式:utf-8
transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
// 7、设置输出属性的第一个元素<bookstore>,换行
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
// 8、第一个参数就是xpath,第二个参数就是文档,第三个参数就是常数节点集
NodeList list=(NodeList)xpath.evaluate("//book[@category='神话小说']", document, XPathConstants.NODESET);
// 9、获取第一个book元素
Element bookelement= (Element)list.item(1);
//10、获取book元素的第一个price元素
Element element=(Element)(bookelement.getElementsByTagName("price").item(0));
// 11、把课本的price属性设置价格为5000元
element.setTextContent("50000");
// 12、创建结果对象
Result result=new StreamResult(System.out);
// 13、通过transformer修改节点。将变化后的结果,输出
transformer.transform(new DOMSource(document), result);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
e.printStackTrace();
} catch (XPathExpressionException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
}