源代码下载:链接: http://pan.baidu.com/s/1ntL1a7R password: rwp1
本文主要讲述:利用Stax处理xml文档
一.读取xml1.基于光标的查找
核心: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("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:/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("com\\tgb\\stax\\v2_iterator\\books.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("com\\tgb\\stax\\v3_filter\\books.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("com\\tgb\\stax\\v4_path\\books.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']", 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.写文档和改动文档