• Java——XMLl解析


    ---恢复内容开始---

    本文章讲解四种 XML 解析方式 :

      DOM 和 SAX 为 Java提供的对 XML 解析的方式,不需要导入 jar 包

      DOM4J 和 JDOM 是其他组织使用他们自己的方式解析 XML 文件,需要我们导入一些 jar 包

    首先我们先看一下 XML 文件

    <School>         -----       父节点
        <student id="1">     ---- 子节点
            <name>小红</name>      ---  这个是student的子节点
            <age>18</age>
            <sex>女</sex>
            <address>北京海定区五道口</address>
        </student>
        <student id="2">      ----    子节点
            <name>小明</name>     
            <age>19</age>
            <sex>男</sex>
            <address>北京海定区上地</address>
        </student>
    </School>

    下面的4种方法统一用上面的 XML 文件 

    第一种  DOM 解析 XML:

    import java.io.IOException;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;
    
    public class Test {
    
        public static void main(String[] args) {
            //创建一个 DocumentBuilderFactory 对象
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            try {
                //创建DocumentBuilder对象
                DocumentBuilder db = dbf.newDocumentBuilder();
                //通过DocumentBuilder的pares方法加载student.xml文件到当前项目下
                Document document = db.parse("School.xml");
                //获取所有 School  下的子节点的集合
                NodeList nodeList = document.getElementsByTagName("student");
                //获取nodeList的长度
                //System.out.println(nodeList.getLength());
                for(int i = 0 ; i < nodeList.getLength() ; i++){
                    
                    System.out.println("**************第"+(i+1)+"名学生***************");
                    
                    //通过item(i) 获取一个student节点,nodeList的索引值从 0 开始
                    Node stu = nodeList.item(i);
                    
                    /**
                     * 第一种不知道student节点的属性和个数
                     */
                    //获取 student 的所有属性集合
                    /*NamedNodeMap attrs = stu.getAttributes();
                    for (int j = 0; j < attrs.getLength(); j++) {
                        
                        Node attr = attrs.item(j);
                        System.out.println("属性名:	"+attr.getNodeName());
                        System.out.println("属性值:	"+attr.getNodeValue());
                    }*/
                    
                    /**
                     * 第二种 知道 student 节点的有且自能有一个 id 属性
                     */
                    //将student节点进行强制类型转换,转换为Element类型
                    /*Element stu = (Element)nodeList.item(i);
                    //通过 getAttribute("id") 方法获取属性值
                    String attribute = stu.getAttribute("id");
                    System.out.println("id的属性值为:"+attribute);*/
                    
                    //获取 student 所有子节点的集合  
                    NodeList childNodes = stu.getChildNodes();
                    
                    for (int j = 0; j < childNodes.getLength(); j++) {
                        Node node = childNodes.item(j);
                        
                        //区分出 text 类型的node 以及 element 下来的 node 
                        if(node.getNodeType() == Node.ELEMENT_NODE){
                            
                            //判断获取到的此节点的名称是否等于name
                            if(node.getNodeName().equals("name")){ 
                                
                                //System.out.println("姓名:	"+node.getFirstChild().getNodeValue());
                                System.out.println("姓名:	"+node.getTextContent());
                                /**
                                 * 说一说这两个的区别
                                 *  node.getFirstChild().getNodeValue() 获取一个子节点的值     并且该节点下不存在子节点,否则返回 null
                                 *  node.getTextContent()  返回此节点下的所有后代 文本内容   
                                 */
                            }
                            
                        }
                    }
                }
                
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    第二种 SAX 解析 XML :

    >>
    创建一个学生类用于接收解析的值
    public class Student {
    
        private int id;
        private String name;
        private int age;
        private String address;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        
    }

    》》创建一个ASXParserHandler 类继承 DefaultHandler 类

    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    public class SAXParserHandler extends DefaultHandler {
    
        private int index=0;
        private String value=null;
        private Student stu = null;
        //为了存储Student 对象
        private List<Student> list = new ArrayList<Student>();
        public List<Student> getList() {
            return list;
        }
        /**
         * 标识解析开始
         */
        @Override
        public void startDocument() throws SAXException {
            super.startDocument();
            //System.out.println("SAX解析开始");
        }
        /**
         * 标识解析结束
         */
        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
            //System.out.println("SAX解析结束");
        }
        
    
        /**
         * 解析 XML元素的
         */
        @Override
        public void  startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            //调用 DefaultHandler 类的 startElement 方法
            super.startElement(uri, localName, qName, attributes);
             
            
            //开始解析 student元素的属性
            if (qName.equals("student")) {
                stu = new Student();
                //index++;    //记录学生 id
                //System.out.println("===========开始遍历第"+index+"名学生的信息=============");
                //已知Student 元素下的属性名称,根据属性名称获取属性值
                /*String vaule = attributes.getValue("id");
                System.out.println(vaule);*/
                //不知到 Student 元素下的属性名称和个数
                for (int i = 0; i < attributes.getLength(); i++) {
                    /*System.out.print("属性名称:"+attributes.getQName(i));
                    System.out.print("----属性值:"+attributes.getValue(i));*/
                    if (attributes.getQName(i).equals("id") ){
                        stu.setId(Integer.parseInt(attributes.getValue(i)));
                    }
                }
            }else if (!qName.equals("School")){
                /*System.out.print("
    节点名是:"+qName);*/
            }
        }
        
        /**
         * 为了遍历xml结束标签   比如这样的  </name>
         */
        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            super.endElement(uri, localName, qName);
            if (qName.equals("student")) {
                //把学生对象添加到集合当中
                list.add(stu); 
                //System.out.println("
    ============结束遍历第"+index+"名学生的信息============");
            }else if (qName.equals("name")) {
                stu.setName(value);
            }
        }
        /**
         * 解析 XML中的内容
         */
        
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            super.characters(ch, start, length);
            
            value = new String(ch,start,length);
            /*if(!value.trim().equals("")){
                System.out.print("----属性值是:"+value);
            }*/
    
        }
        
    }

    》》 解析类

    public static void main(String[] args) {
            //1.通过SaxParserfactory的newInstance()方法获取一个 SAXParserFactory 实例
            SAXParserFactory factory = SAXParserFactory.newInstance();
            
            try {
                //2.通过 factory 获取 SAXParser 实例
                SAXParser parser = factory.newSAXParser();
                
                //创建SAXParserHandler 对象
                SAXParserHandler handler = new  SAXParserHandler();
                //3.
                parser.parse("School.xml", handler);
                
                for (Student item : handler.getList()) {
                    System.out.println(item.getName());
                }
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    送上SAX解析 XML 图一副:

    第三种 JDOM 解析XML :

      准备工作:

        导入 Jar 包 jdom2-2.0.5.jar

        下载地址:http://maven.outofmemory.cn/org.jdom/jdom2/2.0.5/

    import org.jdom2.Document;
    import org.jdom2.Element;
    import org.jdom2.JDOMException;
    import org.jdom2.input.SAXBuilder;
    
    public class JDOMTest {
    
        public static void main(String[] args) {
            //1.创建一个SAXBuilder 对象
            SAXBuilder saxBuilder =new SAXBuilder();
            //创建一个 InputStream 对象
            InputStream is;
            try {
                //创建一个输入流,将 XML 文件加载到输入流
                is = new FileInputStream("School.xml");
                //当出现乱码情况,首先看 XML 当中的 encoding 是不是 utf-8
                //不改变XML encoding 情况下,通过代码防止中文乱码
                InputStreamReader isr = new InputStreamReader(is, "utf-8");
                //通过saxBuilder的build方法,将输入流加载到 saxBuilder中
                Document document = saxBuilder.build(isr);
                //通过 getRootElement 方法获取 XML 的根节点
                Element element = document.getRootElement();
                //获取跟节点下的子节点的集合
                List<Element> stuList = element.getChildren();
                
                for (Element item : stuList) {
                    System.out.println("开始遍历第"+ (stuList.indexOf(item) + 1) +"一个学生的信息");
                    //获取student 属性集合
                    /*List<Attribute> attributes = item.getAttributes();
                    for (Attribute attribute : attributes) {
                        System.out.print("属性名:"+attribute.getName());
                        System.out.println("	属性值:"+attribute.getValue());
                    }*/
                    //对 Student节点的子节点以及节点值遍历
                    List<Element> children = item.getChildren();
                    for (Element stu : children) {
                        if (stu.getName().equals("name")) {
                            System.out.println("姓名是:"+stu.getValue());
                        }
                    }
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }catch (JDOMException | IOException e) {
                e.printStackTrace();
            }        
        }    
    }

     第四种DOM4解析XML:

      准备工作:

      导入 jar 包 :dom4j-1.6.jar

      下载地址:

    import org.dom4j.Attribute;
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    public class Dom4jTest {
    
        public static void main(String[] args) {
            //创建一个 SAXReader 对象
            SAXReader reader = new SAXReader();
            try {
                //通过 reader 对象的 read 方法加载 School.XML文件
                Document document = reader.read(new File("School.xml"));
                //通过document 对象 获取根节点
                Element school = document.getRootElement();
                //通过 Element 对象的 elementIterator 方法获取迭代器
                Iterator it = school.elementIterator();
                //遍历迭代器,获取根节点中的信息
                while(it.hasNext()){
                    //获取到根节点下的一个子节点
                    Element student = (Element) it.next();
                    //获取子节点的属性名以及属性值
                    List<Attribute> list = student.attributes();
                    for (Attribute attribute : list) {
                        //打印属性名称以及属性值
                        System.out.println("属性名:"+attribute.getName()+"	属性值:"+attribute.getValue());
                    }
                    //获取 跟节点下的一个子节点 的所有节点集合
                    Iterator itt = student.elementIterator();
                    //开始遍历这个节点的集合
                    while(itt.hasNext()){
                        //得到每一节点
                        Element studenChild = (Element)itt.next();
                        //打印节点名称以及节点值
                        System.out.println("节点名称:"+studenChild.getName()+"	节点值:"+studenChild.getStringValue());
                    }
                }
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        }
    }

    性能比较:

     DOM :

      优点:

      1.形成了树结构,只观好理解,代码更容易编写

      2.解析过程中树结构保留内存中,方便修改

      缺点:

      1.当 XML 文件较大时,对内存耗费比较大,容易影响解析性能并造成内存溢出

    SAX:

      优点:

      1.采用事件驱动模式,对内存耗费比较小

      2.适用于只需处理 XML 中数据时

    缺点:

      1.不宜编码

      2.很难同时访问同一个 XML中的多处不同数据

    JDOM:

      1.仅仅使用具体类而不使用接口           简化了API 限制了JDOM 的灵活性

      2.API 大量使用了 Collections 类

    DOM4J:

      1.JODM 的一种智能分支,它合并了许多超出基本XML 文档表示功能

      2.DOM4J使用接口和抽象基本类方法,是一个优秀的Java XNL API

      3.具有性能优异、灵活性好、功能强大和极端易用使用特点

      4.是一个开放源代码的软件

     

      

  • 相关阅读:
    django如何给上传的图片重命名(给上传文件重命名)
    Nginx 常见问题解决
    nginx 出现413 Request Entity Too Large问题的解决方法
    python判断一个对象是否可迭代
    InnerClass annotations are missing corresponding EnclosingMember annotations. Such InnerClas...
    Android Studio中新建和引用assets文件
    android 登录效果
    Android (争取做到)最全的底部导航栏实现方法
    抽屉效果的导航菜单
    Android开发之自定义局部导航菜单
  • 原文地址:https://www.cnblogs.com/szj-ang/p/7486133.html
Copyright © 2020-2023  润新知