由于解析spring等相关源码经常要用到xml解析技术,就带大家来复习一下xml技术
一、XML文件
1.1 什么是xml文件
xml是可拓展标记语言,(Extensible Markup Language)就是开发者在符合xml命名规则的基础之上,可以根据自己的需求定义自己的标签;
1.2 xml文件的作用
主要是用来存储数据
1.3 解析xml文件的方法: DOM、DOM4J、SAX
二、DOM4J解析xml文件
2.1 导入Dom4J依赖
2.2 Dom4j的常用对象
2.2.1 SAXReader:读取xml文件到Document树结构文件对象
2.2.2 Document:是一个xml文档对象树,类比Html文档对象
2.2.3 Element:元素节点。通过Document对象可以查找当个元素
2.3 Dom4j解析步骤
2.3.1 创建解析器
SAXReader reader = new SAXReader();
2.3.2 Document对象:通过解析器read方法获取
Document document = saxReader.read("students.xml");
2.3.3 获取xml根节点
Element root = document.getRootElement();
2.3.4 遍历解析子节点
2.4 示例一:使用Dom4j解析students.xml文件
students.xml
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student>
<name>哈哈</name>
<college>java</college>
</student>
<student>
<name>搜索</name>
<college>c++</college>
</student>
<student>
<name>哈哈</name>
<college>app</college>
</student>
</students>
引入依赖
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
Dom4jTest.java
package com.qinghong;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.util.Iterator;
public class Dom4jTest {
public static void main(String[] args) {
// 创建解析器
SAXReader reader = new SAXReader();
// 通过解析器的read将配置文件读取到内存中 生成一个Document[org.dom4j]对象树
try {
Document document = reader.read("students.xml");
// 获取根节点
Element root = document.getRootElement();
// 遍历
for (Iterator<Element> rootIter = root.elementIterator();rootIter.hasNext();){
Element element = rootIter.next();
for (Iterator<Element> innerIter = element.elementIterator();innerIter.hasNext();){
Element next = innerIter.next();
String innerValue = next.getStringValue();
System.out.println(innerValue);
}
System.out.println("------------");
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
得到结果
三、Sax解析xml文件
3.1 SAX方式:事件驱动,边读边写
3.1.1 执行过程如下图
3.1.2 优点:无需将整个文档加载到内存中,所以内存消耗少,适合解析特别大的xml文件
3.1.3 SAX解析四步曲:
(1) 创建解析工厂:通过newInstance()方法获取
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
(2) 创建解析器
SAXParser saxParser = saxParserFactory.newSAXParser();
(3) 调用 parser方法
(4) 原理图如下:
代码实现:
MySAXParser.java
package com.qinghong;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class MySAXParser {
public static void main(String[] args) {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
try {
SAXParser saxParser = saxParserFactory.newSAXParser();
saxParser.parse("students.xml",new MyDefaultHandler());
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyDefaultHandler extends DefaultHandler{
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.println("<" + qName + ">");
}
@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));
}
}
四、使用Dom4j的xPath解析xml文件
4.1 XPath语法
教程:www.w3school.com.cn/xpath/index…
XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。
下面列出了最有用的路径表达式:
选取节点
| 表达式 | 描述 |
|---|---|
| nodename | 选取此节点的所有子节点。 |
| / | 从根节点选取。 |
| // | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
| . | 选取当前节点。 |
| .. | 选取当前节点的父节点。 |
| @ | 选取属性。 |
谓语(Predicates)
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
实例
在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:
| 路径表达式 | 结果 |
|---|---|
| /bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
| /bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
| /bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
| /bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
| //title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
| //title[@lang='eng'] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
| /bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
| /bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
选取未知节点
XPath 通配符可用来选取未知的 XML 元素。
| 通配符 | 描述 |
|---|---|
| * | 匹配任何元素节点。 |
| @* | 匹配任何属性节点。 |
| node() | 匹配任何类型的节点。 |
实例
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
| 路径表达式 | 结果 |
|---|---|
| /bookstore/* | 选取 bookstore 元素的所有子元素。 |
| //* | 选取文档中的所有元素。 |
| //title[@*] | 选取所有带有属性的 title 元素。 |
选取若干路径
通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
实例
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
| 路径表达式 | 结果 | |
|---|---|---|
| //book/title | //book/price | 选取 book 元素的所有 title 和 price 元素。 |
| //title | //price | 选取文档中的所有 title 和 price 元素。 |
| /bookstore/book/title | //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
4.2 实例:获取xml文件的配置信息
准备工作
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
SysConfigParser.java
package com.qinghong;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class SysConfigParser {
public static void main(String[] args) throws DocumentException {
// 构建解析器
SAXReader saxReader = new SAXReader();
// 通过解析器的read方法将配置文件读取到内存中,生成一个Document[dom4j]对象树
Document document = saxReader.read("book.xml");
// title节点元素的xpath路径:/bookstore/book/title
// title节点元素的xpath路径:bookstore//title
// title节点元素的xpath路径://title
Element title = (Element) document.selectSingleNode("//title");
String stringValue = title.getStringValue();
System.out.println(stringValue);
// 获取title节点元素对象的lang属性
Attribute lang = title.attribute("lang");
// 获取lang属性的值
String value = lang.getStringValue();
// 直接获取title节点元素对象的lang属性名字
String s = title.attributeValue("lang");
}
}
五、使用XPath对象解析xml文件
bookstore.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
1.获取bookstore节点下book属性category值为web下的第二个title节点的文本内容
bookstore -> book[@category='web'][2] -> title
xpath路径: /bookstore/book[@category='web'][2]/title/text()
2.获取bookstore节点下book属性category值为web的title属性为en的节点内容
bookstore -> book[@category='web'] -> title[@lang = 'en']
xpath路径: /bookstore/book[@category='web']/title[@lang = 'en']/text()
3.获取bookstore节点下book属性category值为cooking的title的lang属性的值
bookstore -> book[@category='cooking'] -> title -> @lang
xpath路径: /bookstore/book[@category='cooking']/@lang
4.获取bookstore节点下所有book的节点集合
/bookstore/book
-->
<bookstore>
<book category="children">
<title lang="eng">Harry Potter</title>
<price>29.99</price>
<year>2005</year>
</book>
<book category="web">
<title lang="eng">Learning XML</title>
<price>39.95</price>
<year>2003</year>
</book>
<book category="cooking">
<title lang="eng">Everyday Italian</title>
<price>39.95</price>
<year>2003</year>
</book>
<book category="web">
<title lang="uk">XQuery Kick Start</title>
<price>39.95</price>
<year>2003</year>
</book>
</bookstore>
实例:
package com.qinghong;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;
public class MyXPathTest {
public static void main(String[] args){
try {
// 创建解析工厂
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
// 创建解析器
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
// 通过解析器读取配置文件,生成一个import org.w3c.dom.Document包下的
Document document = documentBuilder.parse("bookstore.xml");
// 创建XPath对象
XPath xPath = XPathFactory.newInstance().newXPath();
// bookstore -> book[@category='web'][2] -> title
// xpath路径: /bookstore/book[@category='web'][2]/title/text()
String titleXpath = "/bookstore/book[@category='web'][2]/title/text()";
String titleValue = (String) xPath.evaluate(titleXpath, document, XPathConstants.STRING);
System.out.println(titleValue);
// 2.获取bookstore节点下book属性category值为web的title属性为en的节点内容
// bookstore -> book[@category='web'] -> title[@lang = 'en']
// xpath路径: /bookstore/book[@category='web']/title[@lang = 'en']/text()
String titleXpath2 = "/bookstore/book[@category='web']/title[@lang = 'en']/text()";
String titleValue2 = (String) xPath.evaluate(titleXpath2, document, XPathConstants.STRING);
System.out.println(titleValue2);
// 3.获取bookstore节点下book属性category值为cooking的title的lang属性的值
// bookstore -> book[@category='cooking'] -> title -> @lang
// xpath路径: /bookstore/book[@category='cooking']/@lang
String titleLangAttrXpath = "/bookstore/book[@category='cooking']/@lang";
String titleLangAttrValue = (String) xPath.evaluate(titleLangAttrXpath, document, XPathConstants.STRING);
System.out.println(titleLangAttrValue);
// 4.获取bookstore节点下所有book的节点集合
// /bookstore/book
NodeList nodeList = (NodeList) xPath.evaluate("/bookstore/book", document, XPathConstants.NODESET);
// 开始遍历
for (int i = 0; i < nodeList.getLength(); i++) {
Element item = (Element) nodeList.item(i);
String title = (String) xPath.evaluate("title", item, XPathConstants.STRING);
System.out.println(title);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}