zoukankan      html  css  js  c++  java
  • xml文件解析

    XML,eXtendsible markup language 可扩展的标记语言

    1. 可以用来保存数据

    2. 可以用来做配置文件

    3. 数据传输载体

    XML解析其实就是获取元素里的字符数据或者属性数据

    常用的XML解析方式

    1. DOM:Document Object Model,把整个xml全部读取到内存当中,形成树状结构。整个文档称为document对象,属性对应attribute对象,所有的元素节点对应element对象,文本称之为Text对象,以上所有对象称为Node节点;如果xml特别大可能会造成内存溢出;可以对文档进行增删操作
    2. SAX:Simple API of XML 基于事件驱动。读取一行,解析一行,不会造成内存溢出,不能对文档进行增删,只能查询

    DOM方式解析XML文件

    Document Object Model,把整个xml全部读取到内存当中,形成树状结构。整个文档称为document对象,属性对应attribute对象,所有的元素节点对应element对象,文本称之为Text对象,以上所有对象称为Node节点;如果xml特别大可能会造成内存溢出;可以对文档进行增删操作

    创建一个stus.xml文件,并引入dom4j的jar包

    stus.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <stus>
        <stu>
            <name>wxf</name>
            <age>24</age>
        </stu>
        <stu>
            <name>qf</name>
            <age>18</age>
        </stu>
    </stus>
    View Code

    Dom解析测试类

     1 public class MainTest {
     2     public static void main(String[] args) {
     3         try {
     4             //1.创建SAXReader对象
     5             SAXReader reader = new SAXReader();
     6             //2.读取xml文件,获取Document对象
     7             Document doc = reader.read(new File("src/stus.xml"));
     8             //3.获取document对象的根元素
     9             Element rootElement = doc.getRootElement();
    10             System.out.println("rootElement.getName()==="+rootElement.getName());
    11             System.out.println("--------------");
    12             //4.获取rootElement下的所有子元素
    13             List<Element> elements = rootElement.elements();
    14             for (Element element : elements) {
    15                 System.out.println("element.getName()==="+element.getName());
    16                 System.out.println("name==="+element.element("name").getText());
    17                 System.out.println("age==="+element.element("age").getText());
    18                 System.out.println("--------------");
    19             }
    20         } catch (DocumentException e) {
    21             e.printStackTrace();
    22         }
    23     }
    24 }
    View Code

    console测试结果

    rootElement.getName()===stus
    --------------
    element.getName()===stu
    name===wxf
    age===24
    --------------
    element.getName()===stu
    name===qf
    age===18
    --------------

    dom解析xml文件还可以根据XPath来处理(需要导入jaxen的jar包,否则会抛出java.lang.NoClassDefFoundError: org/jaxen/NamespaceContext

    XPath的常用语法:

    如果路径以斜线 / 开始, 那么该路径就表示到一个元素的绝对路径

    如果路径以双斜线 // 开头, 则表示选择文档中所有满足双斜线//之后规则的元素(无论层级关系)

    星号 * 表示选择所有由星号之前的路径所定位的元素
    ............
    XPath测试类
     1 public class MainTest2 {
     2     public static void main(String[] args) {
     3         try {
     4             //1.创建SAXReader对象
     5             SAXReader reader = new SAXReader();
     6             //2.读取xml文件,获取Document对象
     7             Document doc = reader.read(new File("src/stus.xml"));
     8             //3.根据XPath获取element元素
     9             //查找指定XPath("/")路径下第一个节点
    10             Node selectSingleNode = doc.selectSingleNode("/stus/stu/name");
    11             System.out.println("name==="+selectSingleNode.getText());
    12             System.out.println("==================");
    13             //根据XPath("/")查找所有name节点
    14             List<Node> selectNodes = doc.selectNodes("/stus/stu/name");
    15             for (Node node : selectNodes) {
    16                 System.out.println("name==="+node.getText());
    17             }
    18             System.out.println("==================");
    19             //根据XPath("//")查找所有name节点
    20             List<Node> selectNodes2 = doc.selectNodes("//age");
    21             for (Node node : selectNodes2) {
    22                 System.out.println("age==="+node.getText());
    23             }
    24             System.out.println("==================");
    25             //根据XPath("*")查找stu下的所有子节点
    26             List<Node> selectNodes3 = doc.selectNodes("/stus/stu/*");
    27             for (Node node : selectNodes3) {
    28                 System.out.println(node.getName()+"==="+node.getText());
    29             }
    30         } catch (DocumentException e) {
    31             e.printStackTrace();
    32         }
    33     }
    34 }
    View Code

    console测试结果

    name===wxf
    ==================
    name===wxf
    name===qf
    ==================
    age===24
    age===18
    ==================
    name===wxf
    age===24
    name===qf
    age===18

    SAX解析XML方式

    Java JDK自带的解析。Simple API of XML 基于事件驱动。读取一行,解析一行

    优点:在读取文档的同时即可对XML进行处理,不必等到文档加载结束,相对快捷。不需要加载进内存,因此不存在占用内存的问题,可以解析超大XML

    缺点:只能用来读取XML中数据,无法进行增删改

    SAX解析过程: 

    解析步骤:

    1. 创建一个SAXParserFactory对象:SAXParserFactory factory=SAXParserFactory.newInstance();
    2. 获得解析器 :SAXParser parser=factory.newSAXParser();
    3. 调用解析方法解析xml,这里的第一个参数可以传递文件、流、字符串、需要注意第二个参数(new DefaultHander)
      File file=new File("girls.xml");
      parser.parse(file,new DefaultHandler());
      /**注解:--->这里的DefaultHandler表示
      DefaultHandler类是SAX2事件处理程序的默认基类。它继承了EntityResolver、DTDHandler、
      ContentHandler和ErrorHandler这四个接口。包含这四个接口的所有方法,所以我们在编写事件处理程序时,
      可以不用直接实现这四个接口,而继承该类,然后重写我们需要的方法,所以在这之前我们先定义一个用于实现解析
      方法如下:*/
    4. 创建一个MyHandler类来继承DefaultHandler并重写方法
      //定一个名为MyHandler类用来继承DefaultHandler
      (1)MyHandler extends DefaultHander
      (2)重写方法,快速记住方法(2个开始,2个结束,1一个文字(charactor--里面的内容))
      (3)2个开始:StartDocment(文档的开始)StartElement(元素的开始) 2个结束:endElement(元素的结束)
      endDocment(文档的结束,标志着xml文件的结束) 1个文字内容:charactor(文字内容)
    5. 创建一个集合把所解析的内容添加到集合
      分析:目的我们只是需要把xml里面的文字内容添加到我们的集合而不需要其他元素,所以我们需要进行判断得到
    6. 接步骤三 输出集合System.out.pritnln(list); 解析完成

    创建一个实体类Student.java

     1 package com.qf.pojo;
     2 
     3 public class Student {
     4 
     5     private String name;
     6     private int age;
     7     
     8     public String getName() {
     9         return name;
    10     }
    11     public void setName(String name) {
    12         this.name = name;
    13     }
    14     public int getAge() {
    15         return age;
    16     }
    17     public void setAge(int age) {
    18         this.age = age;
    19     }
    20     @Override
    21     public String toString() {
    22         return "Student [name=" + name + ", age=" + age + "]";
    23     }
    24 }
    View Code

    自定义一个ListHandler类继承DefaultHandler

     1 package com.qf.handler;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 import org.xml.sax.Attributes;
     7 import org.xml.sax.SAXException;
     8 import org.xml.sax.helpers.DefaultHandler;
     9 
    10 import com.qf.pojo.Student;
    11 
    12 public class ListHandler extends DefaultHandler {
    13 
    14     private List<Student> stus;
    15     private Student stu;
    16     private String tag;
    17     
    18     
    19     @Override
    20     public void startDocument() throws SAXException {
    21         //因为这个方法只调用一次,所以在开始的时候就可以实例化集合
    22         stus = new ArrayList<>();
    23     }
    24     @Override
    25     public void endDocument() throws SAXException {
    26         super.endDocument();
    27     }
    28     @Override
    29     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    30         //这个方法,只有当开始一个元素的时候才会调用,
    31         //通过分析,当外部开始元素为student的时候,需要将student实例化
    32         //将tag赋值
    33         tag = qName;
    34         if("stu".equals(qName)) {
    35             stu = new Student();
    36         }
    37     }
    38     @Override
    39     public void endElement(String uri, String localName, String qName) throws SAXException {
    40         //这句话,必须写,因为,当sax解析完一个元素的时候,会自动认为换行符是一个字符,会继续执行 character 方法 。如果不写,就会造成没有数据的现象。 
    41         tag = "";
    42         //这个方法,当到了元素结尾的时候,会调用,应该在这里,将对象添加到集合里面去。
    43         if ("stu".equals(qName)) {
    44             stus.add(stu);
    45         }
    46     }
    47     @Override
    48     public void characters(char[] ch, int start, int length) throws SAXException {
    49         //这里是内容,但是,无法直接判断属于哪一个元素。
    50         String string = new String(ch, start, length);
    51         if ("name".equals(tag)) {//判断当前内容,属于哪一个元素。
    52             stu.setName(string);
    53         }else if ("age".equals(tag)) {
    54             stu.setAge(Integer.valueOf(string));
    55         }//这两种情况,表示 当前语句执行在 stus 标签内。
    56     }
    57     public List<Student> getStus() {
    58         return stus;
    59     }
    60     public void setStus(List<Student> stus) {
    61         this.stus = stus;
    62     }
    63     public Student getStu() {
    64         return stu;
    65     }
    66     public void setStu(Student stu) {
    67         this.stu = stu;
    68     }
    69 }
    View Code

    测试类

     1 package com.qf.test;
     2 
     3 import java.io.File;
     4 import java.io.IOException;
     5 import java.util.List;
     6 
     7 import javax.xml.parsers.ParserConfigurationException;
     8 import javax.xml.parsers.SAXParser;
     9 import javax.xml.parsers.SAXParserFactory;
    10 
    11 import org.xml.sax.SAXException;
    12 
    13 import com.qf.handler.ListHandler;
    14 import com.qf.pojo.Student;
    15 
    16 public class SAXTest {
    17     public static void main(String[] args) {
    18         //1.创建对象
    19         SAXParserFactory newInstance = SAXParserFactory.newInstance();
    20         try {
    21             //2.获取解析器 
    22             SAXParser saxParser = newInstance.newSAXParser();
    23             //3.调用方法开始解析xml   
    24             File file = new File("src/stus.xml");
    25             ListHandler dh = new ListHandler();
    26             saxParser.parse(file, dh);
    27             List<Student> stus=dh.getStus();
    28             //4.输出集合
    29             System.out.println(stus);
    30         } catch (ParserConfigurationException | SAXException e) {
    31             e.printStackTrace();
    32         } catch (IOException e) {
    33             e.printStackTrace();
    34         }
    35     
    36     }
    37 }
    View Code

    控制台输出

    [Student [name=wxf, age=24], Student [name=qf, age=18]]
    

      

  • 相关阅读:
    Hibernate
    Mysql
    JavaWeb
    Springboot
    spring MVC
    spring
    mybatis学习
    ftp客户端封装
    win10子系统 wsl开机启动ssh服务
    eclipse 终于官方支持代码模糊提示了
  • 原文地址:https://www.cnblogs.com/qf123/p/10037171.html
Copyright © 2011-2022 走看看