您的位置:首页 > 编程语言 > Java开发

【JavaEE学习笔记】XML_概述,DOM4J解析器,Pull解析器,DOM4J增删改,xPath

2017-10-14 21:51 701 查看
XML

A.概述

1.起源

W3C万维网联盟,先定义出来的是HTML,XML推出初衷是为了替换HTML

因为HTML语法太过松散,为了规范,推出了XML语言

后来,XML语言用做配置文件,封装数据,版本只有一个v1.0

2.概念

可扩展标记语言:标签可以自定义

命名规范:不能用数字开头,不能使用纯数字,区分大小写

3.功能

a.用做配置文件

b.用做网络数据传输的载体

4.语法

新建一个文本文件,后缀名必须为.xml

5.组成部分

a.文档声明:<?xml version="1.0" encoding="utf-8"?>

encoding告诉浏览用什么编码去解析

文档声明必须在第一行,顶格

b.根标签:有且仅有一个根标签

c.其他标签:有开始标签,一定要有结束标签

d.文本:CDATA区:该区域的文本,会按照纯文本解析

格式:<![CDATA[内容]]>

<?xml version="1.0" encoding="UTF-8"?>
<students>
<student id="s001">
<name>张三</name>
<age>23</age>
<tel>110</tel>
</student>
<student id="s002">
<name>李四</name>
<age>24</age>
<tel>119</tel>
</student>
</students>


6.解析xml

a.DOM

将文档的各个组成部分 抽取一个对象

Element 标签对象

Attribute 属性对象

Text 文本对象

Comment 注释对象

Node 节点对象

Doucment 文档对象

解析过程:将文档一次性,加载进内存,然后将文档各个组成不封抽取为对象

优点:能够对文档进行增删改查

缺点:耗内存,适用于PC端

b.SAX

基于事件,逐行解析,一次读取一行,释放一行

优点:不占内存,适用于移动端

缺点:只能查,不能增删改

7.常用解析器

a.DOM4J:第三方jar包,实现了DOM思想



b.Pull解析器:第三方jar包,实现了SAX思想



B.DOM4J解析器

1.步骤

a.导入DOM4J jar包

b.将上一条的students.xml文件,放入工程根目录

<?xml version="1.0" encoding="UTF-8"?>
<students>	<!-- 根标签 -->
<student id = "s001">	<!-- 子标签 -->
<name>张三</name>
<age>23</age>
<tel>110</tel>
</student>
<student id = "s002">
<name>李四</name>
<age>24</age>
<tel>120</tel>
</student>
</students>


c.代码实现



2.获取标签对象

创建解析器对象

SAXReader reader = new SAXReader();


具体方法在代码中注释

package org.xxxx.dom4j;

import java.io.FileInputStream;
import java.util.Iterator;
import java.util.List;

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

public class DOM4JDemo {
public static void main(String[] args) throws Exception {
// 导入DOM4J jar包
// 创建解析器对象
SAXReader reader = new SAXReader();

// 加载xml文件
Document doc = reader.read(new FileInputStream("students.xml"));

// 获取根标签对象 getRootElement();
Element rootElement = doc.getRootElement();

// 获取根标签下的子标签,默认获取的是第一个子标签 element();
Element stuElement = rootElement.element("student");
System.out.println("根标签下的子标签(默认第一个):" + stuElement.getName());

System.out.println("----------获取所有子标签----------");

// 1)elements();返回结果集
List<Element> ele = rootElement.elements();
for (Element e : ele) {
System.out.println(e.getName());
}

// 2)迭代器获取 elementIterator();
System.out.println("----------迭代器获取所有子标签----------");
Iterator<Element> elementIterator = rootElement.elementIterator();
while (elementIterator.hasNext()) {
Element element = elementIterator.next();
System.out.println(element.getName());
}
}
}


3.获取属性对象和标签之间的文本

三种方式,代码中实现

package org.xxxx.dom4j;

import java.io.FileInputStream;
import java.util.Iterator;
import java.util.List;

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

public class DOM4JDemo {
public static void main(String[] args) throws Exception {
// 导入DOM4J jar包
// 创建解析器对象
SAXReader reader = new SAXReader();

// 加载xml文件
Document doc = reader.read(new FileInputStream("students.xml"));

// 方式1:分布获取属性对象
// 获取跟标签对象
Element rootElement = doc.getRootElement();

// 获取属性对象
Element element = rootElement.element("student");

// 获取属性id attribute("id");
Attribute attribute = element.attribute("id");

// 获取值
String value = attribute.getValue();
String name = attribute.getName();
System.out.println(name + "---" + value);

// 方式2:直接获取属性值
System.out.println("--------------------------");
String value2 = rootElement.element("student").attributeValue("id");
System.out.println(value2);

// 方式3:获取所有属性对象 attributes();
System.out.println("------------------");
List<Attribute> attributes = rootElement.element("student").attributes();
for (Attribute attr : attributes) {
String name2 = attr.getName();
String value3 = attr.getValue();
System.out.println(name2 + "---" + value3);
}

// 通过迭代器获取所有属性对象
System.out.println("------------------");
Iterator<Attribute> attributeIterator = rootElement.element("student").attributeIterator();
while (attributeIterator.hasNext()) {
Attribute attribute2 = attributeIterator.next();
System.out.println(attribute2.getName() + "---" + attribute2.getValue());
}

// 获取标签之间的文本
System.out.println("------------------");
// 方式1:层层往下拿
String text1 = doc.getRootElement().element("student").element("name").getText();
System.out.println(text1);

// 方式2:一步到位
String text2 = doc.getRootElement().element("student").elementText("name");
System.out.println(text2);

}
}


4.获取所有节点

a.node():获取单个节点对象;nodeIterator(); 获取多个节点对象,只能获取子节点

b.获取根标签对象 getRootElement()

c.Element()获取第一个子标签

   Elements() 获取所有的子标签 

   elememtesIterator() 获取所有子标签对象

d.attribute() 获取单个属性对象  getName()获取属性的键  getValue()获取属性的值

   attributes()获取所有的属性对象 

   attributeIterator() 获取所有的属性对象

   直接获取属性对象的值 attributeValue()

e.先获取到文本所在的标签对象 通过getText()拿出这个标签直接的文本elementText("name");

package org.xxxx.dom4j;

import java.io.FileInputStream;
import java.util.Iterator;

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

public class DOM4JDemo {
public static void main(String[] args) throws Exception {
// 导入DOM4J jar包
// 创建解析器对象
SAXReader reader = new SAXReader();

// 加载xml文件
Document doc = reader.read(new FileInputStream("students.xml"));

// 方式1:分布获取属性对象
// 获取跟标签对象
Element rootElement = doc.getRootElement();

// 使用递归获取所有节点
getNodes(rootElement);

}

private static void getNodes(Element ele) {
// 输出当前节点
System.out.println(ele.getName());

// 迭代器获取所有子节点
Iterator<Node> iterator = ele.nodeIterator();

// 遍历
while (iterator.hasNext()) {
Node nodes = iterator.next();
// 判断节电是否属于标签
if (nodes instanceof Element) {
Element eles = (Element) nodes;

// 调用递归
getNodes(eles);
}
}
}
}



5.封装数据

把从xml中解析的数据封装起来

a.创建javabean存放对象

package org.xxxx.dom4j.bean;

import java.io.Serializable;

public class Student implements Serializable {

private static final long serialVersionUID = 1L;

private String id;
private String name;
private String age;
private String tel;

public Student() {
super();
// TODO Auto-generated constructor stub
}

public Student(String id, String name, String age, String tel) {
super();
this.id = id;
this.name = name;
this.age = age;
this.tel = tel;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}

public String getTel() {
return tel;
}

public void setTel(String tel) {
this.tel = tel;
}

@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + ", tel=" + tel + "]";
}

}


b.测试类

package org.xxxx.dom4j;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xxxx.dom4j.bean.Student;

public class FZStudent {
public static void main(String[] args) throws Exception {
// 创建集合存储对象
ArrayList<Student> list = new ArrayList<>();

// 创建解析器
SAXReader reader = new SAXReader();

// 加载xml文件
Document doc = reader.read(new FileInputStream("students.xml"));

// 获取根标签对象
Element rootElement = doc.getRootElement();

// 获取所有的子标签对象
Iterator<Element> elementIterator = rootElement.elementIterator();

// 遍历取出数据并封装
while (elementIterator.hasNext()) {
Element element = elementIterator.next();

// 直接获取属性的值
String id = element.attributeValue("id");

// 获取标签之间的文本
String name = element.elementText("name");
String age = element.elementText("age");
String tel = element.elementText("tel");

// 封装到对象中
Student stu = new Student(id, name, age, tel);

// 添加到集合中
list.add(stu);
}

// 遍历集合
for (Student s : list) {
System.out.println(s.getId() + "---" + s.getName() + "---" + s.getAge() + "---" + s.getTel());
}
}
}



[b]C.Pull解析器


1.概述

SAX:逐行解析,读取一行,释放一行,不占内存

2.需求(序列化与反序列化)

将students.xml文件读取到内存中(反序列化),然后保存到stu.xml文件中去(序列化)

主要方法在代码中注释

注意:写入文档,标签要成对的写

serializer.startDocument("utf-8", true);       // standalone='yes' 文档是否独立

在此写根标签,子标签,都是成对写

serializer.endDocument();     // 文档结束

package org.xxxx.pull;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;
import org.xxxx.pull.bean.Student;

public class PullParseDemo {
// 创建集合,存放对象
private static ArrayList<Student> list;
private static Student student;

public static void main(String[] args) throws Exception {
// 导入jar包
// 获取解析器工厂对象
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

// 获取解析器
XmlPullParser parser = factory.newPullParser();

// 读取文件内容到内存中:反序列化
// 加载文件
// 参数1:要解析的文件 参数2:编码格式
parser.setInput(new FileInputStream("students.xml"), "utf-8");

// 获取事件类型
// 指针默认的位置在文档开始
// 从硬盘中把文件数据读取到内存中,即反序列化
// 获取起始位置
int type = parser.getEventType();

// 一次读取,当判断条件为1,则表示读取到最后一行,结束循环
// 使用XmlPullParse.END_DOCUMENT结束标记,不要直接写1
while (type != XmlPullParser.END_DOCUMENT) {
// 获取标签名称
String tagName = parser.getName();

// 判断
switch (type) {
case XmlPullParser.START_TAG: // 标签开始事件
if ("students".equals(tagName)) {
// 是根标签,创建集合
list = new ArrayList<>();

} else if ("student".equals(tagName)) {
// 子标签,创建javabean对象
student = new Student();

// 获取id
String id = parser.getAttributeValue(0); // 从0开始

// 写入对象
student.setId(id);

} else if ("name".equals(tagName)) {
// 获取标签之间的文本
// String name = parser.getText(); 这个获取不到,注意
String name = parser.nextText();

// 写入对象
student.setName(name);

} else if ("age".equals(tagName)) {
// 获取年龄
String age = parser.nextText();
student.setAge(age);

} else if ("tel".equals(tagName)) {
String tel = parser.nextText();
student.setTel(tel);
}
break;

case XmlPullParser.END_TAG: // 结束标签时间
if ("student".equals(tagName)) {
list.add(student);
}
break;

}
type = parser.next(); // 让指针下移,获取新的事件类型,并重新赋值,防止死循环
}
// 遍历集合,查看是否读取完毕
for (Student stu : list) {
System.out.println(stu.getId() + "---" + stu.getName() + "---" + stu.getAge() + "---" + stu.getTel());
}

System.out.println("--------------------------------");
// 接下来,开始存储数据到stu.xml文件中,也就是序列化
// 抽取一个方法
SavaDataToXML(factory);

}

private static void SavaDataToXML(XmlPullParserFactory factory) throws XmlPullParserException, IllegalArgumentException, IllegalStateException, FileNotFoundException, IOException {
// 获取序列化器
XmlSerializer serializer = factory.newSerializer();

// 设置输出流关联文件
serializer.setOutput(new FileOutputStream("stu.xml"), "utf-8");

// 写入文档声明
// 参数1:编码    参数2:文档是否独立
// 文档开始,也要有文档结束,成对去写
serializer.startDocument("utf-8", true);	// standalone='yes' 文档是否独立

// 写入根标签
// 参数1 命名空间,一般给null   参数2 标签名称
serializer.startTag(null, "students");	// 写入开始标签

// 遍历集合,写子标签
for (Student stu : list) {
// 写入student标签
serializer.startTag(null, "student");

// 写入id属性 参数1 命名空间   参数2 属性名 参数3 属性值
serializer.attribute(null, "id", stu.getId());

// 写入name标签
serializer.startTag(null, "name");

// 写入文本name
serializer.text(stu.getName());

serializer.endTag(null, "name");

// 写入age标签
serializer.startTag(null, "age");

// 写入文本age
serializer.text(stu.getAge());

serializer.endTag(null, "age");

// 写入tel标签
serializer.startTag(null, "tel");

// 写入文本tel
serializer.text(stu.getTel());

serializer.endTag(null, "tel");

// studeng结束标签
serializer.endTag(null, "student");
}

serializer.endTag(null, "students");	// 写入结束标签

serializer.endDocument();	// 文档结束
}
}


运行完毕,刷新工程,查看stu.xml文件



D.DOM4J解析实现增删改

1.修改删除

a.先读取到内存中,进行修改

主要方法

setText();就是设置文本

detach();删除标签

b.重新写入硬盘覆盖掉源文件

XMLWriter 类

c.代码实现

修改以下xml文件

<?xml version="1.0" encoding="UTF-8"?>
<students>
<student id="s001">
<name>张三</name>
<gender>男</gender>
</student>
<student id="s002">
<name>李四</name>
<gender>女</gender>
</student>
</students>修改张三的姓名为王五,性别为空
删除id="002"的属性

package org.xxxx.xml;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;

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

public class Demo01 {
public static void main(String[] args) throws Exception {
// 读取xml文件
SAXReader reader = new SAXReader();
Document doc = reader.read(new FileInputStream("students.xml"));

// 修改文本
// 第一个标签,直接获取
doc.getRootElement().element("student").element("name").setText("王五");
doc.getRootElement().element("student").element("gender").setText("");

// 删除属性
// 获取根标签
Element rootElement = doc.getRootElement();

// 获取属性集
List<Element> elements = rootElement.elements();

// 遍历
for (Element ele : elements) {
// 获取属性
String value = ele.attributeValue("id");

if (value.equals("s002")) {
ele.attribute("id").detach();
}
}

// 重新写入硬盘
XMLWriter writer = new XMLWriter(new FileOutputStream("students.xml"));
writer.write(doc);
writer.close();
}
}



2.增加属性

添加标签:用文档帮助类DocumentHelper,创建一个文档,最后记得XMLWriter 写到硬盘

添加标签:addElement("标签名");

添加属性:addAtrriburte("属性","属性值")

添加文本:addText("文本");

package org.xxxx.xml;

import java.io.FileOutputStream;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.XMLWriter;

public class Demo02 {
public static void main(String[] args) throws Exception {
// 用代码写一个xml
// 文档帮助类写一个声明
Document doc = DocumentHelper.createDocument();

// 添加一个根标签
Element rootEle = doc.addElement("students");

// 添加一个子标签
// 根标签的子标签,用根标签调,后面同理
Element stuELe = rootEle.addElement("student");

// 添加属性
stuELe.addAttribute("id", "s001");

// 添加名字标签
Element name = stuELe.addElement("name");

// 添加名字
name.addText("张三");

// 添加年龄
Element age = stuELe.addElement("age");
age.addText("20");

// 添加电话
Element tel = stuELe.addElement("tel");
tel.addText("110");

// 写到硬盘上
XMLWriter writer = new XMLWriter(new FileOutputStream("mydoc.xml"));
writer.write(doc);
writer.close();
}
}
运行程序,刷新工程



E.xPath

1.概述

路径规则书写的一门技术,它的作用是用来快速找到

XML文档中一个或多个标签,不需要一层一层标签去获取

直接通过标签的特征检索

2.步骤

a.导入DOM4J jar包和支持xPath技术的jar包



b.定义path语句

比如寻找id="s002"的student标签

String path = "//student[@id='s002']";

寻找name为王五的人标签

String path = "//name[text()='王五']";

c.配合xPath找到单个节点对象

Element selectSingleNode = (Element) doc.selectSingleNode(path);
System.out.println(selectSingleNode.getName());

d.找到根标签下的所有标签 selectNodes(path);配合xPath 找到多个节点

String path = "//student";
List<Node> selectNodes = doc.selectNodes(path);
for (Node node : selectNodes) {
System.out.println(node.getName());
}

3.还有很多方法,可以查阅官方文档

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息