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

来源:互联网 发布:hp打印机扫描软件 编辑:程序博客网 时间:2024/05/03 10:48

源码下载链接: 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文件中的:开始元素、内容、结束元素@Testpublic 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("com\\tgb\\stax\\v1_cursor\\books.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:/titlewhile (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 {//测试:读取属性、属性对应的值@Testpublic 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.00while (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 {//测试:读取属性、属性对应的值@Testpublic 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,COOKINGwhile (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值@Testpublic 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("com\\tgb\\stax\\v2_iterator\\books.xml");//基于迭代模型的操作方式XMLEventReader reader = factory.createXMLEventReader(is);int num =0;while (reader.hasNext()){//通过XMLEvent来获取是否是某种节点类型XMLEvent event = reader.nextEvent();//判断是否为:开始节点:START_ELEMENTif (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值@Testpublic 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("com\\tgb\\stax\\v3_filter\\books.xml");//基于Filter的过滤方式,可以有效过滤刁不用进行操作的节点,效率更高一些。XMLEventReader reader = factory.createFilteredReader(factory.createXMLEventReader(is), new EventFilter() {@Overridepublic boolean accept(XMLEvent event) {//返回true表示显示;返回false表示不显示//开始:通过此处过滤以后,效率大幅度提高,num=8if (event.isStartElement()) {String name = event.asStartElement().getName().toString();if ("title".equals(name)||"price".equals(name)) {return true;}}//结束:通过此处过滤以后,效率大幅度提高,num=8return false;}});int num = 0 ;while (reader.hasNext()){//通过XMLEvent来获取是否是某种节点类型XMLEvent event = reader.nextEvent();//判断是否为:开始节点:START_ELEMENTif (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值@Testpublic 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("com\\tgb\\stax\\v4_path\\books.xml");//基于迭代模型的操作方式try {//先创建文档处理对象DocumentBuilderDocumentBuilder 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 {@Testpublic 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 {//描述:修改节点中的值@Testpublic 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-8transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");//设置输出属性的第一个元素<bookstore>,换行transformer.setOutputProperty(OutputKeys.INDENT, "yes");//第一个参数就是xpath,第二个参数就是文档,第三个参数是常数节点集//NodeList list =(NodeList)xPath.evaluate("//book[@category='WEB']", document,XPathConstants.NODESET);NodeList list = (NodeList)xpath.evaluate("//book[title='Learning XML']", document,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.写文档和修改文档 


2 0
原创粉丝点击