加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

WebService(2)-XML系列之用Stax操作Xml

发布时间:2020-12-16 22:45:46 所属栏目:安全 来源:网络整理
导读:源码下载 : 链接:?http://pan.baidu.com/s/1ntL1a7R?密码: rwp1 本文主要讲述:利用Stax处理xml文档 一.读取xml? 1.基于光标的查找? 核心:XMLInputFactory,XMLStreamReader 好处:效率最高 坏处:但是操作不方便 TestStax_readElement.java package com.t

源码下载链接:?http://pan.baidu.com/s/1ntL1a7R?密码: rwp1

本文主要讲述:利用Stax处理xml文档

一.读取xml?

1.基于光标的查找?

核心:XMLInputFactory,XMLStreamReader

好处:效率最高

坏处:但是操作不方便

TestStax_readElement.java

package com.tgb.stax.v1_cursor;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.junit.Test;
/**
 * 通过光标方式读取XML文件-读取开始节点START_ELEMENT、结束节点END_ELEMENT、文本节点CHARACTERS
 * @author 赵栗婧
 * @version 1.0.0,2015年6月25日 下午12:12:55
 */
public class TestStax_readElement {

	//通过XMLInputFactory,读取xml文件中的:开始元素、内容、结束元素
	@Test
	public void testReadElement() {

		XMLInputFactory factory = XMLInputFactory.newInstance();
		InputStream is = null;
		try {
			//以下是读取路径文件的两种方式(注意此处的路径问题!):
			is=TestStax_readElement.class.getClassLoader().getResourceAsStream("com/tgb/stax/v1_cursor/books.xml");
			//is = TestStax.class.getClassLoader().getResourceAsStream("comtgbstaxv1_cursorbooks.xml");
			System.out.println("IS:" + is);
			XMLStreamReader reader = factory.createXMLStreamReader(is);
			// 范例解析:
			// type:1 START_ELEMENT:title
			// type:4 CHARACTERS:Everyday Italian
			// type:2 END_ELEMENT:/title
			while (reader.hasNext()) {
				int type = reader.next();
				// 打印出:节点类型
				System.out.println("type:" + type);
				//如果是:开始元素节点,则打印
				if (type == XMLStreamConstants.START_ELEMENT) {
					System.out.println("START_ELEMENT:"	+ reader.getName().toString());					
				} else if (type == XMLStreamConstants.CHARACTERS) {
					//如果是文本节点,则打印
					System.out.println("    CHARACTERS:"	+ reader.getText().trim());
				} else if (type == XMLStreamConstants.END_ELEMENT) {
					//如果是结束元素节点,则打印
					System.out.println("END_ELEMENT:/" + reader.getName());
				}

			}
		} catch (FactoryConfigurationError e) {
			e.printStackTrace();
		} catch (XMLStreamException e) {
			e.printStackTrace();
		} finally {
			//如果输入流InputStream不为空,则手动关闭
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

TestStax_readElementText.java

package com.tgb.stax.v1_cursor;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.junit.Test;
/**
 * 通过光标方式读取XML文件-根据START_ELEMEN的名称,读取ElementText
 * @author 赵栗婧
 * @version 1.0.0,2015年6月25日 下午12:12:55
 */
public class TestStax_readElementText {

	//测试:读取属性、属性对应的值
	@Test
	public void testReadElementText(){
		XMLInputFactory factory =XMLInputFactory.newInstance();
		InputStream is =null;
		try {
			is=TestStax_readElementText.class.getClassLoader().getResourceAsStream("com/tgb/stax/v1_cursor/books.xml");
			XMLStreamReader reader = factory.createXMLStreamReader(is);		
			//范例:读取ElementText
			//读取:<title lang="en">Everyday Italian</title>			
			//    <price>30.00</price>
			//根据title,读取Everyday Italian
			//根据price读取:30.00
			while (reader.hasNext()) {
				int type = reader.next();
				if (type==XMLStreamConstants.START_ELEMENT) {
					String name = reader.getName().toString();
					if ("title".equals(name)) {
						System.out.println("title:"+reader.getElementText());
					}
					if ("price".equals(name)) {
						System.out.println("price:"+reader.getElementText());
					}
				}
				
			}
		} catch (FactoryConfigurationError | XMLStreamException e) {
			e.printStackTrace();
		}finally{
			try {
				if (is!=null) 	is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		
	}
}

TestStax_readAttributeValue.java

package com.tgb.stax.v1_cursor;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.junit.Test;

/**
 * 通过光标方式读取XML文件-根据START_ELEMEN的名称,读取Attribute和Value
 * @author 赵栗婧
 * @version 1.0.0,2015年6月25日 下午12:12:55
 */
public class TestStax_readAttributeValue {

	//测试:读取属性、属性对应的值
	@Test
	public void testReadAttributeValue(){
		XMLInputFactory factory =XMLInputFactory.newInstance();
		InputStream is =null;
		try {
			is=TestStax_readAttributeValue.class.getClassLoader().getResourceAsStream("com/tgb/stax/v1_cursor/books.xml");
			XMLStreamReader reader = factory.createXMLStreamReader(is);
		
			//范例:
			//读取:<book category="COOKING">中,START_ELEMENT=book的相应信息
			//结果为:category,COOKING
			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 (FactoryConfigurationError | XMLStreamException e) {
			e.printStackTrace();
		}finally{
			try {
				if (is!=null) 	is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		
	}
	
}

2.基于迭代器模型的查找?

通过XMLEventReader,根据开始节点名称START_ELEMENT,获取对应的ElementText值

TestStax_iterator.java

package com.tgb.stax.v2_iterator;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.XMLEvent;

import org.junit.Test;

/**
 * 采用迭代器的方式操作XML文档
 * @author 赵栗婧
 * @version 1.0.0,2015年6月25日 下午12:11:47
 */
public class TestStax_iterator {

	//通过XMLEventReader,根据开始节点名称START_ELEMENT,获取对应的ElementText值
	@Test
	public void testReadElement() {

		XMLInputFactory factory = XMLInputFactory.newInstance();
		InputStream is = null;
		try {
			//以下是读取路径文件的两种方式(注意此处的路径问题!):
			is=TestStax_iterator.class.getClassLoader().getResourceAsStream("com/tgb/stax/v2_iterator/books.xml");
			//is = TestStax.class.getClassLoader().getResourceAsStream("comtgbstaxv2_iteratorbooks.xml");
			//基于迭代模型的操作方式
			XMLEventReader reader = factory.createXMLEventReader(is);
			int num =0;
			while (reader.hasNext()){
				//通过XMLEvent来获取是否是某种节点类型
				XMLEvent event = reader.nextEvent();
				//判断是否为:开始节点:START_ELEMENT
				if (event.isStartElement()) {
					//通过event.as***转化为节点
					String name =event.asStartElement().getName().toString();
					if ("title".equals(name)) {
						System.out.println("ElementText:"+reader.getElementText());
					}
				}
				num++;
			}
			//结果是93条
			System.out.println("num:"+num);
			
		} catch (FactoryConfigurationError e) {
			e.printStackTrace();
		} catch (XMLStreamException e) {
			e.printStackTrace();
		} finally {
			//如果输入流InputStream不为空,则手动关闭
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	}


3.基于过滤器

点评:基于光标/迭代器,都是建立在遍历整个文档的基础之上。

过滤器,过滤掉了我们不需要的文档

?* 采用过滤器的方式操作XML文件
? ? ? ? * 若在XMLEventReader的构造函数中,不使用过滤,则需要循环num=25次
? ? ? ? * 若在XMLEventReader的构造函数中,使用title和price过滤,则需要循环num=8次,效率更高
?* 而v2_iterator迭代器的方式,效率更低num=93


TestStax_filter.java

package com.tgb.stax.v3_filter;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.stream.EventFilter;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.XMLEvent;

import org.junit.Test;

/**
 * 采用过滤器的方式操作XML文件
	 * 若在XMLEventReader的构造函数中,不使用过滤,则需要循环num=25次
	 * 若在XMLEventReader的构造函数中,使用title和price过滤,则需要循环num=8次,效率更高
 * 而v2_iterator迭代器的方式,效率更低num=93
 * @author 赵栗婧
 * @version 1.0.0,2015年6月25日 下午12:04:28
 */
public class TestStax_filter {

	//通过XMLEventReader,根据开始节点名称START_ELEMENT,获取对应的ElementText值
	@Test
	public void testReadElement() {

		XMLInputFactory factory = XMLInputFactory.newInstance();
		InputStream is = null;
		try {
			//以下是读取路径文件的两种方式(注意此处的路径问题!):
			is=TestStax_filter.class.getClassLoader().getResourceAsStream("com/tgb/stax/v3_filter/books.xml");
			//is = TestStax.class.getClassLoader().getResourceAsStream("comtgbstaxv3_filterbooks.xml");
			//基于Filter的过滤方式,可以有效过滤刁不用进行操作的节点,效率更高一些。
			XMLEventReader reader = factory.createFilteredReader(factory.createXMLEventReader(is),new EventFilter() {						
						@Override
						public boolean accept(XMLEvent event) {
							//返回true表示显示;返回false表示不显示
							//开始:通过此处过滤以后,效率大幅度提高,num=8
							if (event.isStartElement()) {
								String name = event.asStartElement().getName().toString();
								if ("title".equals(name)||"price".equals(name)) {
									
									return true;
								}
							}
							//结束:通过此处过滤以后,效率大幅度提高,num=8
							return false;
						}
					});
			int num = 0 ;
			while (reader.hasNext()){
				//通过XMLEvent来获取是否是某种节点类型
				XMLEvent event = reader.nextEvent();
				//判断是否为:开始节点:START_ELEMENT
				if (event.isStartElement()) {
					//通过event.as***转化为节点
					String name =event.asStartElement().getName().toString();
					if ("title".equals(name)) {
						System.out.print("title:"+reader.getElementText()+"-------->");
					}else if ("price".equals(name)) {
						System.out.println("price:"+reader.getElementText());
					}
				}
				num++;
			}
			//此处结果是25条
			//若在XMLEventReader的构造函数中,使用title和price过滤,则num=8,效率更高
			System.out.println("num:"+num);
		} catch (FactoryConfigurationError e) {
			e.printStackTrace();
		} catch (XMLStreamException e) {
			e.printStackTrace();
		} finally {
			//如果输入流InputStream不为空,则手动关闭
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	}


4.基于xpath的处理?

此处采用xpath方式操作XML文档。(需要把xml文档【Document】读进来)
?* 效率不高
?* 不一定加载全部文档源,可以截取的
好处:获取节点最好的方式?

缺点:需要加载整个文档?

TestStax_xpath.java

package com.tgb.stax.v4_xpath;

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.FactoryConfigurationError;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.XMLEvent;
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;

/**
 * 此处采用xpath方式操作XML文档。(需要把xml文档【Document】读进来)
 * 效率不高
 * 不一定加载全部文档源,可以截取的
 * @author 赵栗婧
 * @version 1.0.0,2015年6月25日 下午12:10:48
 */
public class TestStax_xpath {

	//通过XMLEventReader,根据开始节点名称START_ELEMENT,获取对应的ElementText值
	@Test
	public void testReadElement() {

		XMLInputFactory factory = XMLInputFactory.newInstance();
		InputStream is = null;
		int num=0;
			//以下是读取路径文件的两种方式(注意此处的路径问题!):
			is=TestStax_xpath.class.getClassLoader().getResourceAsStream("com/tgb/stax/v4_xpath/books.xml");
			//is = TestStax.class.getClassLoader().getResourceAsStream("comtgbstaxv4_pathbooks.xml");
			//基于迭代模型的操作方式
			try {
				//先创建文档处理对象DocumentBuilder
				DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
				//通过DocumentBuilder创建Document文档对象
				Document document = db.parse(is);
				//创建XPath对象
				XPath xPath=XPathFactory.newInstance().newXPath();
				//第一个参数就是xpath,第二个参数就是文档,第三个参数是常数节点集
				NodeList list =(NodeList)xPath.evaluate("//book[@category='WEB']",document,XPathConstants.NODESET);
				//遍历输出相应结果
				for(int i=0;i<list.getLength();i++){
					Element e = (Element) list.item(i);
					System.out.print(e.getElementsByTagName("title").item(0).getTextContent());
					System.out.print(":");
					System.out.println(e.getElementsByTagName("price").item(0).getTextContent());
					num++;
				}
				System.out.println("num:"+num);
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			} catch (SAXException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (XPathExpressionException e) {
				e.printStackTrace();
			}finally{
				//关闭输入流
				if (is != null) {
					try {
						is.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			
			
		

	}

	}

二.写文档和修改文档?

使用XMLStreamWriter创建XML

package com.tgb.stax.v5_writeandeditxml;

import java.io.IOException;
import java.io.InputStream;

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 org.junit.Test;

/**
 * 利用XMLStreamWriter 代码中写一个XML文件
 * @author 赵栗婧
 * @version 1.0.0,2015年6月26日 上午10:32:52
 */
public class TestStax_writexml {

	@Test
	public void testReadElement() {
		
			try {
				
				//注意顺序
				System.out.println("---Demo:第一个(没有命名空间)-------------------------------------------");				
				//第一个,结果
				//<?xml version="1.0" encoding="UTF-8"?>
				//<people>
				//	<id>
				//		1070541038
				//	</id>
				//</people>
				XMLStreamWriter xsw = XMLOutputFactory.newInstance().createXMLStreamWriter(System.out);
				xsw.writeStartDocument("UTF-8","1.0");
				xsw.writeEndDocument();
				xsw.writeStartElement("people");				
				xsw.writeStartElement("id");
				xsw.writeCharacters("1070541038");
				xsw.writeEndElement();
				xsw.writeEndElement();
				xsw.flush();//清空
				xsw.close();//关闭
				
				System.out.println();
				System.out.println("---Demo:第二个(添加命名空间)-------------------------------------------");
				//Demo:第二个(添加命名空间),结果
				//<?xml version="1.0" encoding="UTF-8"?>
				//<namespace_lizi:person>
				//	<namespace_lizi:id>
				//		1070541038
				//	</namespace_lizi:id>
				//</namespace_lizi:person>
				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("1070541038");
				xsw2.writeEndElement();
				xsw2.writeEndElement();
				xsw2.flush();
				xsw2.close();
			} catch (XMLStreamException e) {
				e.printStackTrace();
			} catch (FactoryConfigurationError e) {
				e.printStackTrace();
			}		
	}
}

使用Transformer更新节点信息

package com.tgb.stax.v5_writeandeditxml;

import static org.junit.Assert.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.xml.crypto.dsig.Transform;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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;
/**
 * 利用Transformer修改XML中节点信息
 * @author 赵栗婧
 * @version 1.0.0,2015年6月26日 上午10:33:21
 */
public class TestStax_editxml {

	//描述:修改节点中的值
	@Test
	public void testeditxml() {
		InputStream is = null;
		
		try {
			//读取路径文件
			is = TestStax_editxml.class.getResourceAsStream("books.xml");
			//先创建文档处理对象
			DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			//通过文档处理对象,创建文档对象
			Document document = db.parse(is);
			//创建XPath对象
			XPath xpath = XPathFactory.newInstance().newXPath();
			//创建Transformer对象
			Transformer transformer =  TransformerFactory.newInstance().newTransformer();
			//设置输出属性的编码格式:UTF-8
			transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
			//设置输出属性的第一个元素<bookstore>,换行
			transformer.setOutputProperty(OutputKeys.INDENT,"yes");
			
			//第一个参数就是xpath,第二个参数就是文档,第三个参数是常数节点集
			//NodeList list =(NodeList)xPath.evaluate("//book[@category='WEB']",XPathConstants.NODESET);
			NodeList list = (NodeList)xpath.evaluate("//book[title='Learning XML']",XPathConstants.NODESET);
			//获取第一个book元素
			Element bookElement = (Element)list.item(0);
			//获取book元素中的第一个price元素
			Element element =(Element)(bookElement.getElementsByTagName("price").item(0));
			//把课本的price属性设置价格为5000元
			element.setTextContent("5000");
			//创建结果对象
			Result result = new StreamResult(System.out);
			//通过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();
		}finally{
			//关闭输入流
			if (is!=null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}		
		
	}

}

三.总结

本文主要讲述了通过stax操作XML文件。

1.读取xml 的4种方式:
? ? 1).基于光标的查找?
? ? 2).基于迭代器模型的查找?
? ? 3).基于过滤器
? ? 4).基于xpath的处理


?点评:基于光标/迭代器,都是建立在遍历整个文档的基础之上。
?过滤器,过滤掉了我们不需要的内容,效率更高。
?xpath方式,需要把xml文档都读进来(可以截取),效率不高


2.写文档和修改文档?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读