StAX处理xml(Stream API for XML)

利用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();
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值