• Java对XML文档的解析


    1、 DOM解析

       DOM的全称是Document Object Model,也即文档对象模型。DOM解析会将XML文档以对象树的方式存入内存,因此,DOM解析内存消耗巨大。当然由于DOM解析将XML以节点树的方式调入内存,所以对文档进行增删改查(crud)比较方便。DOM分析器把整个XML文档转化成DOM树放在了内存中,因此,当文档比较大或者结构比较复杂时,对内存的需求就比较高。而且,对于结构复杂的树的遍历也是一项耗时的操作。所以,DOM分析器对机器性能的要求比较高,实现效率不十分理想。

    -------------------------book.xml-----------------------------------------------
    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <书架>
        <书>
            <书名>javaweb</书名>
            <作者>xiehe</作者>
            <售价>889.00元</售价>
        </书>
        <书>
            <书名>javaweb2</书名>
            <作者>hehe</作者>
            <售价>8.00元</售价>
        </书>
    </书架>
    ------------------------------------------------------------------------------------
    package it.xiehe.xml;
    
    import java.io.FileOutputStream;
    import java.text.AttributedCharacterIterator.Attribute;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    
    import org.junit.Test;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    
    public class Demo02 {
    
        //1、读取xml文档内容
        @Test
        public void read() throws Exception{
             DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
             DocumentBuilder builder=factory.newDocumentBuilder();
             Document document=builder.parse("src/it/xiehe/xml/book.xml");
             
             NodeList  list=document.getElementsByTagName("书名");
             Node node= list.item(0);
            
             String content= node.getTextContent();
             System.out.println(content);
        }
        //递归遍历节点
        @Test
        public void read1() throws Exception{
             DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
             DocumentBuilder builder=factory.newDocumentBuilder();
             Document document=builder.parse("src/it/xiehe/xml/book.xml");
             
            Node node=document.getElementsByTagName("书架").item(0);
            list(node);
        }
        private void list(Node node) {
            System.out.println(node.getTextContent());
            NodeList list=node.getChildNodes();
            for(int i=0;i<list.getLength();i++){
                Node child=list.item(i);
                list(child);
            }
            
        }
        //增加一个节点
        @Test
        public void add() throws Exception{
            //1、获取document
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            DocumentBuilder builder=factory.newDocumentBuilder();
            Document document=builder.parse("src/it/xiehe/xml/book.xml");
            
            //2、增加节点 <售价>57.00元</售价>
            //1>创建节点
            Element piece=document.createElement("售价");
            piece.setTextContent("57.00元");
            //2>把创建的节点挂到第一本书上
            Element book=(Element) document.getElementsByTagName("书").item(0);
            book.appendChild(piece);
            //3将修改的xml文件回写
            TransformerFactory tffactory=TransformerFactory.newInstance();
            Transformer tf=tffactory.newTransformer();
            tf.transform(new DOMSource(document),
            new StreamResult(new FileOutputStream("src/it/xiehe/xml/book.xml")));
            
        }
    }

    2、SAX解析
      SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口。

      需要注意的是,SAX解析XML文档时,空白不能忽略。

    package it.xiehe.xml;
    
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    import javax.xml.transform.sax.SAXTransformerFactory;
    
    import org.junit.Test;
    import org.xml.sax.Attributes;
    import org.xml.sax.ContentHandler;
    import org.xml.sax.Locator;
    import org.xml.sax.SAXException;
    import org.xml.sax.XMLReader;
    
    public class DemoSAX {
    
        @Test
        public void test01() throws Exception, Exception {
            // 1 创建sax工厂
            SAXParserFactory factory = SAXParserFactory.newInstance();
            // 2 得到解析器
            SAXParser parser = factory.newSAXParser();
            // 3 得到读取器
            XMLReader reader = parser.getXMLReader();
            // 4 设置内容处理器
            // 不同的功能对应不同的处理器,一般通过继承DefaultHandler覆盖其中的方法
            reader.setContentHandler(new ListHandler());
            // 5 读取xml文件内容
            reader.parse("src/Book.xml");
        }
    
    }
    //1、打印出xml文件所有内容
    //通过实现ContentHandler接口对XML文档进行处理
    class ListHandler implements ContentHandler{
    
        @Override
        public void setDocumentLocator(Locator locator) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void startDocument() throws SAXException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void endDocument() throws SAXException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void startPrefixMapping(String prefix, String uri)
                throws SAXException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void endPrefixMapping(String prefix) throws SAXException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes atts) throws SAXException {
            //这里对获取到的元素进行处理,暂时先输出吧!
           System.out.println("<"+qName+">");
           for(int i=0;atts!=null&&i<atts.getLength();i++){
               String name=atts.getQName(i);
               String value=atts.getValue(i);
               System.out.println(name+"="+value);
           }
           
        }
    
        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            // TODO Auto-generated method stub
            System.out.println("<"+qName+">");
        }
    
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            // TODO Auto-generated method stub
            System.out.println(new String(ch,start,length));
        }
    
        @Override
        public void ignorableWhitespace(char[] ch, int start, int length)
                throws SAXException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void processingInstruction(String target, String data)
                throws SAXException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void skippedEntity(String name) throws SAXException {
            // TODO Auto-generated method stub
            
        }}
    -------------------------------获得XML文档数据并且封装到对象中----------------------
    package it.xiehe.xml;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    import javax.xml.transform.sax.SAXTransformerFactory;
    
    import org.junit.Test;
    import org.xml.sax.Attributes;
    import org.xml.sax.ContentHandler;
    import org.xml.sax.Locator;
    import org.xml.sax.SAXException;
    import org.xml.sax.XMLReader;
    import org.xml.sax.helpers.DefaultHandler;
    
    public class Demo03SAX {
    
        @Test
        public void test01() throws Exception, Exception {
            // 1 创建sax工厂
            SAXParserFactory factory = SAXParserFactory.newInstance();
            // 2 得到解析器
            SAXParser parser = factory.newSAXParser();
            // 3 得到读取器
            XMLReader reader = parser.getXMLReader();
            // 4 设置内容处理器
            BeanListHandler handler=new BeanListHandler();
            reader.setContentHandler(handler);
            // 5 读取xml文件内容
            reader.parse("src/it/xiehe/xml/book.xml");
            List<book> list=handler.getBook();
            for(book b:list){
                System.out.println(b);
            }
        }
    
    }
    
    // 3、打印出xml文件所有内容用book对象封装
    //这里通过继承DefaultHandler类覆盖里面我们需要的方法实现想要的功能
    class BeanListHandler extends DefaultHandler {
    
        private String TagContent;//记录标签内容
        private book b;//
        List list = new ArrayList();//存储book对象
    
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            TagContent = qName;
            if ("书".equals(TagContent)) {
                b = new book();
                
            }
    
        }
    
        public List getBook() {
            return list;
        }
    
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            
            if ("书名".equals(TagContent)) {
                String name = new String(ch, start, length);
                b.setName(name);
            }
            if ("作者".equals(TagContent)) {
                String author = new String(ch, start, length);
                b.setAuthor(author);
            }
            if ("售价".equals(TagContent)) {
                String price = new String(ch, start, length);
                b.setPrice(price);
            }
        }
    
        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            if ("书".equals(qName)) {
                list.add(b);
                b=null;
            }
            //此处需要重置,不然会有错误的
            TagContent = null;
        }
    
    }
    ---------------------------------book类封装-------------------------------------------
    package it.xiehe.xml;
    
    public class book {
     
        private String name;
        private String author;
        private String price;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAuthor() {
            return author;
        }
        public void setAuthor(String author) {
            this.author = author;
        }
        public String getPrice() {
            return price;
        }
        public void setPrice(String price) {
            this.price = price;
        }
        @Override
        public String toString() {
            return "书名:"+name+" 作者:"+author+" 价格:"+price;
        }
        
    }

    2、dom4j

     对主流的Java XML API进行的性能、功能和易用性的评测,dom4j无论在那个方面都是非常出色的。如今你可以看到越来越多的Java软件都在使用dom4j来读写XML,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。使用Dom4j时,可以通过查看他本身的的文档快速入门使用,在使用过程中尤其注意中文乱码问腿。

    package it.xiehe.xml;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.FileWriter;
    import java.io.OutputStreamWriter;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.OutputFormat;
    import org.dom4j.io.SAXReader;
    import org.dom4j.io.XMLWriter;
    import org.junit.Test;
    
    public class DemoDom4j {
    
        // 使用Dom4j读取xml中的内容:<书名>javaweb1</书名>
        @Test
        public void read() throws Exception {
    
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File("src/it/xiehe/xml/book.xml"));
            // 获得根节点
            Element root = document.getRootElement();
            // Dom4j比较笨,需要从根结点一层层往下取数据
            // 当xml中有属性 (attribute)取法与之类似
            Element book = (Element) root.elements("书").get(0);// 此处从list集合中取出,所以需要类型强转
            String name = book.element("书名").getText();
            System.out.println(name);
        }
    
        // 增加第一本书的售价2:<售价>88.00元</售价>
        // 中文乱码问题有待解决
        @Test
        public void add() throws Exception {
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File("src/it/xiehe/xml/book.xml"));
            // 获得根节点
            Element root = document.getRootElement();
            // 在<书>节点下增加一个节点<售价>到内存中去
            root.element("书").addElement("售价").addText("88.00元");
            // 从内存中写回xml文件中
    
            // XMLWriter 将文件交给Filewriter写入xml文档中,后者自动调用本地编码GB2312码编码产生乱码
            /*
             * XMLWriter writer = new XMLWriter(new FileWriter(
             * "src/it/xiehe/xml/book.xml"));
             */
            /*
             * //查询api可以知道,OutputStreamWriter 可以指定编码方式,所以使用它指定UTF-8 XMLWriter writer
             * = new XMLWriter(new OutputStreamWriter( new
             * FileOutputStream("src/it/xiehe/xml/book.xml"), "UTF-8"));
             * writer.write(document); writer.close();
             */
            // 在开发中,常用的方法是设置一个格式化输出器
            // Pretty print the document to System.out
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
            XMLWriter writer = new XMLWriter(new FileOutputStream(
                    "src/it/xiehe/xml/book.xml"), format);
            writer.write(document);
            writer.close();
        }
    }

    下面是使用dom4j增删改查的小例子

    package it.xiehe.xml;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.util.List;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.DocumentHelper;
    import org.dom4j.Element;
    import org.dom4j.io.OutputFormat;
    import org.dom4j.io.SAXReader;
    import org.dom4j.io.XMLWriter;
    import org.junit.Test;
    
    public class DomeDom4j02 {
    
        // 将<售价>888.00元</售价>添加到指定位置(第二本书的作者后面)
        @Test
        public void add() throws Exception {
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File("src/it/xiehe/xml/book.xml"));
            // 获得根节点
            Element root = document.getRootElement();
            Element book = (Element) root.elements("书").get(1);
    
            List list = book.elements();// [书名 作者 售价]
            // 创建新节点
            Element price = DocumentHelper.createElement("售价");
            price.setText("888.00元");
            // 添加到list集合中指定位置
            list.add(2, price);
            // 更新到xml文档中
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
    
            XMLWriter writer = new XMLWriter(new FileOutputStream(
                    "src/it/xiehe/xml/book.xml"), format);
            writer.write(document);
            writer.close();
        }
    
        // 删除刚刚添加的节点(获得该节点的爸爸节点删除自己)
        @Test
        public void delete() throws Exception {
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File("src/it/xiehe/xml/book.xml"));
            // 获得根节点
            Element root = document.getRootElement();
    
            Element book = (Element) root.elements("书").get(1);
            Element price = (Element) book.elements("售价").get(0);
            price.getParent().remove(price);
            // 更新到xml文档中
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
    
            XMLWriter writer = new XMLWriter(new FileOutputStream(
                    "src/it/xiehe/xml/book.xml"), format);
            writer.write(document);
            writer.close();
        }
    
        // 更新节点信息第一本书<售价>88.00元</售价>变为<售价>66.00元</售价>
        @Test
        public void update() throws Exception {
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File("src/it/xiehe/xml/book.xml"));
            // 获得根节点
            Element root = document.getRootElement();
    
            Element book = (Element) root.elements("书").get(0);
            Element price = (Element) book.elements("售价").get(1);
            price.setText("66.00元");
            // 更新到xml文档中
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
    
            XMLWriter writer = new XMLWriter(new FileOutputStream(
                    "src/it/xiehe/xml/book.xml"), format);
            writer.write(document);
            writer.close();
    
        }
    }
  • 相关阅读:
    连接数据库的几种方式
    c#拖拽文件
    设置webbrowser浏览器内核
    C#控件置于底层或顶层
    C#中读取xml文件指定节点
    关于selenium python Message: unknown error: Element is not clickable at point错误
    Linux的命令操作
    MySQL数据库的知识
    没有添加main方法
    eclipse导入已建工程
  • 原文地址:https://www.cnblogs.com/he-shao/p/5347635.html
Copyright © 2020-2023  润新知