DOM解析
JAVA提供的默认解析XML文档的方式, 实现了w3c中的标准, 应用最广泛.
dom是个功能强大的解析工具,适用于小文档. 它会把整篇xml文档装载进内存中,形成一颗文档对象树
简单使用
/**
* DOM解析测试类
*
* @author jssd
* Create 2019-07-10 18:31
*/
public class Test {
public static void main(String[] args) {
// 1. 取得文档建立工厂
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
// 2. 获取文档建立对象
DocumentBuilder documentBuilder;
try {
documentBuilder = documentBuilderFactory.newDocumentBuilder();
// 3. 通过文档建立对象取得文档对象
Document document = documentBuilder.parse("books.xml");
// 4. 通过元素名, 取得元素对象
NodeList noteList = document.getElementsByTagName("books");
// 查看取得元素对象个数
System.out.println("根元素个数" + noteList.getLength());
System.out.println("====================查看元素属性======================");
for (int i = 0; i < noteList.getLength(); i++) {
// 取得单个对象
Node item = noteList.item(i);
// 取得所有属性
NamedNodeMap attributes = item.getAttributes();
// 循环遍历所有属性, 并输出
System.out.println(item.getNodeName() + "节点的所有属性如下: ");
for (int j = 0; j < attributes.getLength(); j++) {
Node node = attributes.item(j);
System.out.println(node.getNodeName() + ": " + node.getNodeValue());
}
System.out.println("=============查看元素内节点或文本内容============");
// 取得所有子元素节点
NodeList childNodes = item.getChildNodes();
System.out.println("childNodes.getLength() = " + childNodes.getLength());
/*
DOM解析的过程中, 可以看到字节点中有空的文本节点, 我们查看的时候需要过滤出来
*/
for (int j = 0; j < childNodes.getLength(); j++) {
Node node = childNodes.item(j);
if (node.getNodeType() == Node.ELEMENT_NODE) {
// 查看节点名和节点值
System.out.println("childNodes.item(j) = " + node.getNodeName() + ":" + node.getNodeValue());
}
}
}
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
}
SAX解析
和DOM一样, 同样是JAVA原生组件, 全称是simple API for XML
SAX 是一种以事件驱动的XML API, SAX去DOM不同的是它边扫描边解析, 自顶向下依次解析, 由于边扫描边解析, 所以它解析XML具有速度快, 占用内存少的优点
简单使用:
/**
* @author jssd
* Create 2019-07-10 19:14
*/
public class Test {
public static void main(String[] args) {
// 1. 取得SAX解析器工厂
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
// 2. 从sax解析器工厂中取得解析器
SAXParser saxParser;
try {
saxParser = saxParserFactory.newSAXParser();
// 3. 重写DefaultHandler类, 使用DefaultHandler类中的方法, 解析XML
BookHandler bookHandler = new BookHandler();
// 4. 开始解析
saxParser.parse(new File("books.xml"), bookHandler);
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
}
使用SAX的时候, 需要有个类继承DefaultHandler
/**
* @author jssd
* Create 2019-07-10 19:19
*/
public class BookHandler extends DefaultHandler {
// 文档开始解析的时候调用
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("文档开始解析");
}
// 文档解析结束的时候调用
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("文档解析结束");
}
// 元素开始解析的时候调用
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
System.out.println("元素属性: ");
if (attributes.getLength() != 0) {
for (int i = 0; i < attributes.getLength(); i++) {
System.out.println("attributes.getQName() + attributes.getValue() = " +
attributes.getQName(i) + ": " + attributes.getValue(i));
}
}
System.out.println("元素名: " + qName);
}
// 元素解析结束的时候调用
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
}
// 解析XML中的文本时候调用
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String str = new String(ch, start, length);
if(!"".equals(str.trim())) { // 过滤空的文本节点
System.out.println("文本内容为: " + str);
}
}
}
JDOM解析
JDOM是第三方插件, 不属于JAVA原生解析方式, 所以需要导入jar包
它基于树型结构,利用纯 Java 的技术对 XML 文档实现解析。所以只适合于 Java
语言
简单步骤:
- 创建一个SAXBuilder 对象
- 调用SAXBuilder对象的build方法, 得到Document对象(通过IO流)
- 获取根节点
- 获取根节点的直接子节点的集合
- 遍历集合
简单使用:
注意: 使用的时候导包不要导错了
/**
* JDom 学习测试类
* @author jssd
* Create 2019-07-11 14:01
*/
public class Test {
public static void main(String[] args) {
// 取得SAXBuilder对象
SAXBuilder saxBuilder = new SAXBuilder();
try {
// 取得整个文档
Document document = saxBuilder.build("books.xml");
// 从文档中取得根节点
Element rootElement = document.getRootElement();
// 从根节点中取出子节点
List children = rootElement.getChildren();
for (Object child : children) {
Element element = (Element) child;
// 查看子节点的属性
List attributes = element.getAttributes();
for (Object attribute : attributes) {
Attribute att = (Attribute) attribute;
System.out.println("att.getName = " + att.getName() + ", att.getValue = " + att.getValue());
}
}
// 查看子节点的内容
for (Object child : children) {
Element element = (Element) child;
List subChild = element.getChildren();
for (Object o : subChild) {
Element subEle = (Element)o;
System.out.println("subEle.getName() = " + subEle.getName());
System.out.println("subEle.getValue() = " + subEle.getValue());
}
}
} catch (JDOMException | IOException e) {
e.printStackTrace();
}
}
}
dom4j解析
DOM4J 是一个 Java 的 XML API, 是 JDOM 的升级品,用来读写 XML 文件的
解析步骤:
- 创建SAXReader对象
- 调用read方法
- 过去根元素
- 通过迭代器遍历直接节点
简单使用:
/**
* @author jssd
* Create 2019-07-11 14:31
*/
public class Test {
public static void main(String[] args) {
SAXReader saxReader = new SAXReader();
try {
// 取得文档
Document document = saxReader.read("books.xml");
// 取得根元素
Element rootElement = document.getRootElement();
// 取得根元素之下的子元素
for (Iterator iter = rootElement.elementIterator(); iter.hasNext(); ) {
Element bookEle = (Element) iter.next();
// 获取子元素的属性
for (Iterator iterator = bookEle.attributeIterator(); iterator.hasNext(); ) {
Attribute bookAttr = (Attribute) iterator.next();
System.out.println("属性的名字: " + bookAttr.getName() + ", 属性的值: " + bookAttr.getValue());
}
for (Iterator iterator = bookEle.elementIterator(); iterator.hasNext(); ) {
Element element = (Element) iterator.next();
System.out.println("子节点的值: " + element.getName() + ", 子节点的值: " + element.getText());
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
四种解析方式比较
-
DOM解析
形成了树的结构, 有助于更好的理解, 掌握, 且代码容易编写. 解析过程中, 树结构保存在内存中, 方便修改
-
SAX解析
采用事件驱动模式, 对内存的耗费比较小. 适用于只处理XML文件中的数据时
-
JDOM解析
仅使用具体类, 而不使用接口, API大量使用了Collections类
-
DOM4J解析
JDOM的一种只能分支, 它合并了许多超出基本XML文档表示的功能. 它使用接口和抽象基本类方法. 具有性能优异, 灵活性好, 功能强大和极端易用的特点. 开源.
DOM4J配合XPATH快速选择一个元素
我们使用DOM4J解析XML的时候, 有的时候元素层数比较多, 难道要一个一个元素的取得进去吗? 显然, XML层数多了之后, 就不现实了. 所以我们有了XPATH技术.
XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言。XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初 XPath 的提出的初衷是将其作为一个通用的、介于XPointer与XSLT间的语法模型。但是 XPath 很快的被开发者采用来当作小型查询语言。
小知识: 使用chrome浏览器打开一个网页的时候, 按f12 查看源代码, 右键网页中html元素, 可以copyXpath
简单使用:
假如我有一个XML如下
<?xml version="1.0" encoding="utf-8" ?>
<books xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="books.xsd">
<book id="1111">
<name>java 实战开发</name>
<author>jssd</author>
<price>1000</price>
</book>
<book id="1001">
<name>java开发实战</name>
<author>张小三</author>
<price>98.5</price>
</book>
</books>
查找指定元素:
public class Test {
public static void main(String[] args) {
// 获取DOM4J中的SAXReader对象
SAXReader saxReader = new SAXReader();
Document read;
try {
// 读取整个文档
read = saxReader.read("books.xml");
// 我想要选中id=1001中book的author节点
Node node = read.selectSingleNode("//book[@id=1001]/author");
System.out.println("node.getName() + \", \" + node.getText() = " + node.getName() + ", " + node.getText());
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
XPath使用非常简单, 就是配合DOM4J进行选择节点, 关于XPath语法, 本文不做介绍, 请查阅相关API