xml


1. xml是什么?

xml: 可扩展标记语言


2. xml的应用场景

  • 用于数据传输的格式
  • 用于配置文件

3. 标签的分类

单标签:

双标签: 标签体

4. xml的名词

标签: 单标签和双标签

  • xml文件必须有一个声明部分 <?xml version="1.0" encoding="utf-8"?>,声明部分必须放在首行(开始位置)
  • 一个xml文件有且只有一个根标签
  • xml的标签必须闭合 ,即使是单标签也必须闭合;
  • xml标签可以携带属性,称为标签属性,标签属性可以有多个,标签属性的值必须使用引号括起来
  • 双标签中的内容称为标签体
  • xml可以表示树结构
  • xml中的对象都是节点(node)
    • 标签节点
    • 属性节点: AttributeNode
    • 文本节点
  • xml可以有约束(dtd,schemaer)
  • 建议: 标签的节点建议使用英文小写
  • xml文件放置位置:根目录下创建目录resources(资源),然后将此目录作为Resources Root(右键鼠标–>Mark Directory as–>Resources Root)

5. Xml的解析

  • Dom解析
  • Sax解析
  • Dom4j解析
  • Jdom解析
  • Pull解析
  • Xpath解析
  • ….

6.Dom解析

Dom解析是把xml文件读取并且加载到内存中,形成树结构,我们称为DOM树,我们就可以查找节点的值;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.xzy.xmlstydy.dom;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
* 使用Dom解析xml
* 把文档加载到内存中形成DOM树
*/
public class DomParseApp {
public static void main(String[] args) throws Exception {
//1. 创建Dom解析器工厂
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//2. 使用解析器工厂创建解析器
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//3. 使用解析器解析xml,返回一个Document对象
InputStream ins = DomParseApp.class.getClassLoader().getResourceAsStream("books.xml");
Document document = documentBuilder.parse(ins);
//获取根节点
Element rootElement = document.getDocumentElement();

//通过根节点获取子节点,9个子节点
NodeList childNodes = rootElement.getChildNodes();
//遍历所有的子节点
for (int i = 0; i < childNodes.getLength(); i++) {
//过滤出来元素(Element)类型的节点
Node node1 = childNodes.item(i);
if (node1.getNodeType() == Node.ELEMENT_NODE) {
//获取book元素节点
Element bookElement = (Element) node1;
Attr attrId = bookElement.getAttributeNode("id");
System.out.println("id=" + attrId.getValue());
NodeList childNodes1 = bookElement.getChildNodes();
for (int j = 0; j < childNodes1.getLength(); j++) {
if (childNodes1.item(j).getNodeType() == Node.ELEMENT_NODE) {
String nodeName = childNodes1.item(j).getNodeName();
Text textNode = (Text) childNodes1.item(j).getChildNodes().item(0);
String nodeValue = textNode.getNodeValue();
System.out.println(nodeName + "=" + nodeValue);
}
}
System.out.println("----------------------------");
}
}
}
}

优点

   1. 解析简单
      2. 符合树结构

缺点

  1. 不适合大文件的解析
  2. 大文件加载到内存中有可能出现内存溢出(堆内存溢出) OOM

7. Sax解析

不是基于Dom树的解析,它是基于事件驱动的解析方式;不会把文档加载到内存中;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.xzy.xmlstydy.sax;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;

/**
* Sax解析Xml
*/
public class SaxPaserApp {
public static void main(String[] args) throws Exception {
//创建Sax解析器工厂
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
//使用Sax解析器工厂创建Sax解析器
SAXParser saxParser = saxParserFactory.newSAXParser();
//使用Sax解析器解析xml
InputStream ins = SaxPaserApp.class.getClassLoader().getResourceAsStream("books.xml");
saxParser.parse(ins, new DefaultHandler() {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.println("开始解析:" + qName);
if (qName.equals("book")) {

System.out.println("---------------"+attributes.getValue("id")+"----------------------");
}
}

@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println("结束解析:" + qName);
}

@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.println("内容:" + new String(ch, start, length));
}
});
}
}

优点:

  1. 可以解析大文件(基于事件驱动)

缺点:

  1. api设计的不好
  2. 不适合解析小文件

8. Dom解析与Sax解析的选择

如果没有特殊要求,一律选择Dom解析,如果有大文件需要解析,可以考虑使用Sax解析


9. Dom4J解析xml

  • dom4J不是jdk内置的解析xml的解决方案
  • 是一个开源的解析xml的解决方案(jar包)
  • 我们在实际的开发过程中会经常的使用dom4j解析xml
  • dom4j基于dom树进行解析的
  • 我们使用dom4J解析xml时需要导入jar包,在根目录中创建目录lib,将夹包放入其中,右键lib目录,点击Add as Library

10. 使用dom4J解析xml

  • 准备一个jar包

    image-20211110191453600

  • 把jar包作为库

  • 使用dom4j提供的库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.xzy.xmlstydy.dom4j;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.List;

public class Dom4jParserApp {
public static void main(String[] args) throws Exception {
//创建dom4j解析器
SAXReader saxReader = new SAXReader();
//解析xml返回一个Document对象
Document document = saxReader.read(Dom4jParserApp.class.getClassLoader().getResourceAsStream("books.xml"));
//获取根节点
Element rootElement = document.getRootElement();

//获取book子元素
List <Element>elements = rootElement.elements("book");

for (Element bookElement : elements) {
String id = bookElement.attributeValue("id");
System.out.println(id);
List<Element> elements1 = bookElement.elements();
for (Element element : elements1) {
System.out.println(element.getName()+"="+element.getStringValue());
}
}
}
}


11. xpath表达式解析xml

  • xpath表达式解析xml要配合dom4j进行使用
1
2
3
4
5
/: 出现在表达式的开始位置代表文档的根,非开始位置代表 "子"
//: 出现在开始位置代表从任意位置开始查找,非开始位置代表 "后代"
@id:获取到属性节点(属性节点是所在元素节点的子节点)
text();获取文本节点(文本节点是其所属元素节点的子节点)
[@id=3]:用属性作为条件; eg: /books/book[@id=3]/name/text()

文章作者: Yang Shiyu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yang Shiyu !
  目录