xml文件解析

Posted qf123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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]]

  

以上是关于xml文件解析的主要内容,如果未能解决你的问题,请参考以下文章

在Tomcat的安装目录下conf目录下的server.xml文件中增加一个xml代码片段,该代码片段中每个属性的含义与用途

DOM解析xml文件

无法解析片段中的 findViewById [重复]

java解析xml的几种方式哪种最好?

Expat Parser解析xml文件

jsoup解析xml某片段的问题