涉及知识点 :dom4j, XPath, 递归
知识点:
节点是比元素更大一层的概念, 元素节点仅仅是节点中的一种.
元素,属性,名字空间,注释,文本内容,处理指令,还有整个文档(即看成根节点),这7种都是节点。那么元素节点仅仅是其中的一种。
XML解析:
* 解析xml可以做:
* 如果xml作为配置文件:读取
* 如果xml作为传输文件:写,读
* xml解析思想:
* DOM:将文档加载进内存,形成一颗dom树(document对象),将文档的各个组成部分封装为一些对象。
* 优点:因为,在内存中会形成dom树,可以对dom树进行增删改查。
* 缺点:dom树非常占内存,解析速度慢。
Document
Element
Text
Attribute
Comment
* SAX:逐行读取,基于事件驱动
* 优点:不占内存,速度快
* 缺点:只能读取,不能回写
* xml常用的解析器:
* JAXP:sun公司提供的解析。支持dom和sax。
* JDOM:
*
DOM4J:
dom for java民间方式,但是是事实方式。
非常好。
支持dom
1.导入jar包 dom4j.jar
2.创建解析器
SAXReader reader = new SAXReader();
3.解析xml 获得document对象
Document document = reader.read(url);
*
XPATH: 基于路径的解析, -----> 专门用于查询
* 定义了一种规则。
* 使用的方法:(只有两个)
* selectSingleNode():
* selectNodes():
使用步骤:
1、注意:要导包 jaxen...jar
2、创建解析器
SAXReader reader = new SAXReader();
3、解析xml 获得document对象
Document document = reader.read(url);
注意:
使用Dom4j需要到1个依赖 dom4j
Jaxen is a universal Java XPath engine.
使用XPath,要导两个依赖 dom4j 和 jaxen
----------------------------------------------------------------------------------------------------------------------------------------------------
本案例使用maven构建一jar工程:
pom文件只添加了两个依赖:
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
素材:books.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<books group="pager">
<!--第一本书-->
<book id="1001" class="shu">
<name>java葵花宝典</name>
<author>张三</author>
<price>9.9</price>
</book>
<!--第二本书-->
<book id="1002" class="shu">
<name>java葵花宝典(第二部)</name>
<author>李四</author>
<price>999.9</price>
</book>
That's all!
</books>
测试类TestDom4jParse:
测试方法:testPath:-->测试XPath的用法
/**
* 获得第二本书的作者
* @throws DocumentException
*/
@Test
public void testXPath() throws DocumentException {
//创建SAX读取器
SAXReader reader=new SAXReader();
//获得document对象
Document document = reader.read("src\\test\\resources\\books.xml");
Node node = document.selectSingleNode("/books/book[2]/author");// path(节点基于路径化去找)
System.out.println(node.getText());
}
测试结果:
李四
测试方法:testPath2:-->测试XPath的用法
/**
* 遍历所有开始标签
* @throws DocumentException
*/
@Test
public void testXPath2() throws DocumentException {
SAXReader reader=new SAXReader();
Document document = reader.read("src\\test\\resources\\books.xml");
List nodes = document.selectNodes("//*");
for (int i = 0; i < nodes.size(); i++) {
Node node=(Node) nodes.get(i);
System.out.println(node.getName()+"="+node.getText());
}
}
运行结果:
测试方法:testGetAll() --->前戏: 证明节点和Element不是姨妈事
@Test
public void testGetAll() throws DocumentException {
//创建SAX读取器
SAXReader reader=new SAXReader();
//获得document对象
Document document = reader.read("src\\test\\resources\\books.xml");
//获得根元素
Element rootElement = document.getRootElement();
System.out.println(rootElement.attributeCount()); //0
//遍历根元素的属性
for (int i = 0; i < rootElement.attributeCount(); i++) {
Attribute attribute = rootElement.attribute(i);
System.out.println(attribute.getName()+"="+attribute.getValue());
}
System.out.println("rootElement:"+rootElement.getName()+"="+rootElement.getText().trim());//去两头空白
System.out.println("----------------------------------------");
System.out.println(rootElement.nodeCount()); //9
System.out.println(rootElement.elements().size()); //2
System.out.println("--------------可见node和element是有区别的---------------");
List elements = rootElement.elements();
for (int i = 0; i < elements.size(); i++) {
Element childElement = (Element) elements.get(i);
System.out.println("childElement:"+childElement.getName()+"="+childElement.getText());
}
}
测试结果:
测试方法:testGetAll2() --->正式开始 (用到了递归)
@Test
public void testGetAll2() throws DocumentException {
//创建SAX读取器
SAXReader reader=new SAXReader();
//获得document对象
Document document = reader.read("src\\test\\resources\\books.xml");
//获得根元素
Element rootElement = document.getRootElement();
//根元素的文本内容
System.out.println("rootElement的文本内容:"+rootElement.getName()+"="+rootElement.getText().trim());
List attributes = rootElement.attributes();
if (attributes.size()>0) {
for (int i = 0; i < attributes.size(); i++) {
// 返回值类型 Object
Attribute attribute=(Attribute) attributes.get(i);
System.out.println("rootElement:"+attribute.getName()+"="+attribute.getValue());
}
}
treewalk(rootElement);
}
//元素递归
public void treewalk(Element element) {
if (element.elements().size()>0) {
List elements = element.elements();
for (int i = 0; i < elements.size(); i++) {
//返回值类型 Object
Element childElement=(Element) elements.get(i);
System.out.println("childElement的文本内容:"+childElement.getName()+"="+childElement.getText().trim());
List attributes = childElement.attributes();
if (attributes.size()>0) {
for (int j = 0; j < attributes.size(); j++) {
//返回值类型 Object
Attribute attribute = (Attribute) attributes.get(j);
System.out.println(attribute.getName()+"="+attribute.getValue());
}
}
if (childElement.elements().size()>0) {
treewalk(childElement);
}
}
}else {
// 结束 ---- 递归结束条件
}
}
测试结果: