美文网首页
Tomcat相关技术-Digester(一)XML文件解析技术

Tomcat相关技术-Digester(一)XML文件解析技术

作者: 贪睡的企鹅 | 来源:发表于2019-08-05 17:02 被阅读0次

    1 XML文件解析技术

    Java解析XML文件有两个主要的实现方式:预加载DOM树事件机制的SAX

    2 预加载DOM树

    2.1 设计思想
    • 预加载DOM树是将整个XML文件数据读取到内存中,构造出一个DOM树对象,接着实现一套解析DOM树对象API。
    2.2 具体实现
    • 对于预加载DOM树,JAVA提供了两种实现JDOM,DOM4J。这两种方法的思路都是一样的,只不过一个是Java官方实现,一个是社区出的实现。
    2.3 该思想有优点和缺点
    • 优点:使用DOM时,XML文档的结构在内存中很清晰,元素与元素之间的关系完整保留在内存对象中。
    • 缺点:如果XML文档非常大,将整个XML文档装在进内存容易造成内容溢出,。
    2.4 案例

    加载需要的jar包

    <dependency>
          <groupId>org.dom4j</groupId>
          <artifactId>dom4j</artifactId>
          <version>2.1.0</version>
        </dependency>
    

    创建需要解析的xml

    <books>
        <book author="天蚕土豆">
            <name>斗破苍穹</name>
            <price>86</price>
        </book>
        <book author="萧潜">
            <name>缥缈之旅</name>
            <price>92</price>
        </book>
        <book author="萧鼎">
            <name>诛仙</name>
            <price>98</price>
        </book>
        <book author="天下霸唱">
            <name>鬼吹灯</name>
            <price>124</price>
        </book>
        <book author="辰东">
            <name>神墓</name>
            <price>128</price>
        </book>
    </books>
    

    解析实例

    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    import java.util.List;
    
    public class Dom4JTest {
    
        public static void main(String[] args) throws DocumentException {
            SAXReader saxReader = new SAXReader();
            //document 加载执行xml文档获取Document对象
            Document document = saxReader.read(Dom4JTest.class.getResource("/books.xml"));
            //2.获取根元素的对象 -- books getRootElement 获取根元素
            Element rootElement = document.getRootElement();
            //每个元素的对象 都是Element对象
            List<Element> elements = rootElement.elements();
            //3.使用根元素的对象  对其他元素操作操作
            //3.1获取所有的子元素对象 book
            for (Element book : elements) {
                //在循环内拿到了 每个 book  元素对象
                //3.2获取book的属性值
                String author = book.attributeValue("author");
                //3.3获取book的子元素  name price
                String name = book.element("name").getText();
                String price = book.element("price").getText();
                System.out.println(name + " " + author + " " + price);
            }
        }
    }
    

    2 事件机制的SAX

    2.1 设计思想
    • 一行一行的读取XML文件,每当读取到一个xml节点,就看看注册到该节点监听器事件是否被触发,如果有就触发该通知监听器去解析xml节点。解析xml过程中内存里不会保存任何数据。
    2.2 具体实现
    • 对于事件机制的SAX,JAVA 官方提供了实现
    2.3 该思想有优点和缺点
    • 优点:使用SAX不会占用大量内存来保存XML文档数据,效率高。
    • 缺点:当解析一个元素时,上一个元素的信息已经丢弃,也就是说没有保存元素与元素之间的结构关系。
    2.4 案例

    创建需要解析的xml

    <?xml version="1.0" encoding="UTF-8"?>
    <PeopleList>
        <People id="1">
            <Name en='zhangsan'>张三</Name>
            <Age>20</Age>
        </People>
        <People id="2">
            <Name en='lisi'>李四</Name>
            <Age>30</Age>
        </People>
    </PeopleList>
    

    创建解析完成构建的model

    public class People {
        private String id;
        private String name;
        private String englishName;
        private String age;
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getEnglishName() {
            return englishName;
        }
        public void setEnglishName(String englishName) {
            this.englishName = englishName;
        }
        public String getAge() {
            return age;
        }
        public void setAge(String age) {
            this.age = age;
        }
    
    }
    

    创建解析器

    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 解析器需要继承DefaultHandler类
     */
    public class SaxHandler extends DefaultHandler {
    
        //解析完成创建的model
        private List<People> peoples = null;
        //临时存储当前正在解析的People
        private People people;
        //临时存放挡墙解析的标签
        private String currentTag = null;
        //临时存放当前解析标签中字符  <>字符<>
        private String currentValue = null;
        //
        private String nodeName = null;
    
        public List<People> getPeoples() {
            return peoples;
        }
    
        public SaxHandler(String nodeName) {
            this.nodeName = nodeName;
        }
    
        /**
         * 触发解析一个xml文件开始事件时调用
         */
        @Override
        public void startDocument() throws SAXException {
            // TODO 当读到一个开始标签的时候,会触发这个方法
            super.startDocument();
            //初始化peoples
            peoples = new ArrayList<People>();
        }
    
        /**
         * 触发解析一个xml文件结束事件时调用
         */
        @Override
        public void endDocument() throws SAXException {
            // TODO 自动生成的方法存根
            super.endDocument();
        }
    
        /**
         * 触发解析一个xml标签开始事件时调用
         * @param uri
         * @param localName
         * @param name        当前标签的名称
         * @param attributes  标签中的属性
         * @throws SAXException
         */
        @Override
        public void startElement(String uri, String localName, String name,
                                 Attributes attributes) throws SAXException {
            // TODO 当遇到文档的开头的时候,调用这个方法
            super.startElement(uri, localName, name, attributes);
    
            if (name.equals(nodeName)) {
                people = new People();
            }
            if (attributes != null && people != null) {
                for (int i = 0; i < attributes.getLength(); i++) {
                    if(attributes.getQName(i).equals("id")){
                        people.setId(attributes.getValue(i));
                    }
                    else if(attributes.getQName(i).equals("en")){
                        people.setEnglishName(attributes.getValue(i));
                    }
                }
            }
            currentTag = name;
        }
    
    
        /**
         * 触发解析一个xml标签结束事件时调用
         * @param uri
         * @param localName
         * @param name        当前标签的名称
         * @throws SAXException
         */
        @Override
        public void endElement(String uri, String localName, String name)
                throws SAXException {
            // TODO 在遇到结束标签的时候,调用这个方法
            super.endElement(uri, localName, name);
    
            if (name.equals(nodeName)) {
                peoples.add(people);
            }
        }
    
    
        /**
         * 触发解析一个xml标签中字符调用(startElement触发之后endElement触发之前)
         * @param ch  xml文档完整字符
         * @param start   当前标签中字符在ch开始位置
         * @param length  当前标签中字符的长度
         * @throws SAXException
         */
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            // TODO 这个方法用来处理在XML文件中读到的内容
            super.characters(ch, start, length);
    
            if (currentTag != null && people != null) {
                currentValue = new String(ch, start, length);
                if (currentValue != null && !currentValue.trim().equals("") && !currentValue.trim().equals("\n")) {
                    if(currentTag.equals("Name")){
                        people.setName(currentValue);
                    }
                    else if(currentTag.equals("Age")){
                        people.setAge(currentValue);
                    }
                }
            }
            currentTag = null;
            currentValue = null;
        }
    
    
    }
    

    测试代码

    import java.util.List;
    
    public class SaxTest {
    
        public static void main(String[] args) throws Exception {
    
            try {
                SAXParserFactory spf = SAXParserFactory.newInstance();
                SAXParser parser = spf.newSAXParser();
                SaxHandler handler = new SaxHandler("People");
                parser.parse(Dom4JTest.class.getResource("/People.xml").openStream(), handler);
    
                List<People> peopleList = handler.getPeoples();
                for(People people : peopleList){
                    System.out.println(people.getId()+"\t"+people.getName()+"\t"+people.getEnglishName()+"\t"+people.getAge());
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Tomcat相关技术-Digester(一)XML文件解析技术

          本文链接:https://www.haomeiwen.com/subject/joomdctx.html