xml文档里包含的是xml的元素,指的是从开始标签直到结束标签的部分,元素里可以包含其他元素,元素也可以拥有其他属性,比如:
<students>
<student id="1">
<name>yang</name>
<age>25</age>
<stuNo>1212</stuNo>
</student>
</students>
students,student,name,age,stuNo等这些都叫元素标签也可以叫元素节点和元素对象。
id是某个元素的节点的属性,叫属性节点和属性对象。
yang,25,1212等这样的数据叫做值,也可以叫做文本节点和文本对象。
实体引用:xml中有若干符号,是跟xml有冲突的,所以需要用别名代替
实体引用 字符 说明
< < 小于
> > 大于
& & 与
&aops; ' 单引号
" " 双引号
比如:
<name>1<2</name>
<desc>这个是一个"描述"文本</desc>
CDATA段
格式:<![CDATA][文本内容]]>
特殊标签中的实体引用被忽略,所有内容被当成一整块文本数据。
<?xml version="1.0" encoding="UTF-8"?>
<root>
<![CDATA[
<hello>
<worl>
]]>
<subRoot> </subRoot>
</root>
SAX解析方式:(simple api for xml)是一种xml解析的替代方法,想对比DOM解析,sax解析是一种速度快,更有效的方法,因为他是逐行扫描xml文档,一边扫描一边解析而且相对于dom解析,sax可以在解析文档的任意时刻停止解析。
优点:解析可以立即开始,速度快,没有内存压力。
缺点:不能对节点做修改。
sax解析必须借助第三方工具dom4j,工具中提供若干jar包,jar包中提供了若干api来解析xml,dom4j是一个非常优秀的解析xml框架,也是一个开源的框架。
/**
* 1. 用SAX解析XML,获取文档对象
*/
@Test
public void test01() throws DocumentException {
SAXReader sax = new SAXReader();
// 1. 指定XML件的位置路径
Document document1 = sax.read("src/main/resources/employee.xml");
System.out.println(document1);
// 2.从类路径下获取XML文件
InputStream is = TestAnnotationClass.class.getClassLoader().getResourceAsStream("employee.xml");
Document document2 = sax.read(is);
System.out.println(document2);
// 结果
// org.dom4j.tree.DefaultDocument@18ef96 [Document: name src/main/resources/employee.xml]
// org.dom4j.tree.DefaultDocument@769c9116 [Document: name null]
}
/**
* 2. 用SAX解析XML,获取文档的根节点对象
*/
@Test
public void test03() throws DocumentException {
SAXReader sax = new SAXReader();
InputStream is = TestAnnotationClass.class.getClassLoader().getResourceAsStream("employee.xml");
Document document = sax.read(is);
// 从文件对象中获取文档的根节点
Element root = document.getRootElement();
System.out.println(root);
// 结果
// org.dom4j.tree.DefaultElement@6956de9 [Element:
]
}
/**
* 3. 用SAX解析XML,从根节点获取根节点下的所有的儿子元素节点
*/
@Test
public void test04() throws DocumentException {
// 准备一个集合,用来存储遍历到的节点
List<Employee> employees = new ArrayList<Employee>();
// 获取SAX对象
SAXReader sax = new SAXReader();
InputStream is = TestAnnotationClass.class.getClassLoader().getResourceAsStream("employee.xml");
// 获取文档对象
Document document = sax.read(is);
// 获取文档的根节点对象
Element root = document.getRootElement();
// 获取当前节点下的所有元素节点返回List集合
List<Element> emps_Element = root.elements();
// 循环遍历元素
for (Element emp : emps_Element) {
// 获取当前节点的某一个属性名对应的属性对象,返回值是Attribute类的对象,从Attribute类的对象获取当前属性对象中的属性值
int id = Integer.parseInt(emp.attribute("id").getValue());
// 获取当前元素节点里的文本节点的值
String name = emp.element("name").getText();
// 获取当前元素节点里的文本节点的值
int age = Integer.parseInt(emp.element("age").getText());
// 获取当前元素节点下的指定元素节点名称的节点里的文本节点的值
String gender = emp.elementText("gender");
// 获取当前元素节点下的指定元素节点名称的节点里的文本节点的值
double salary = Double.parseDouble(emp.elementText("salary"));
// 构造函数
Employee e = new Employee(id, name, age, gender, salary);
// 存入集合
employees.add(e);
}
System.out.println(employees);
// 结果
// [Employee [id=6, name=杨, age=20, gebder=男, sal=2000.0], Employee [id=7, name=杨, age=20, gebder=男,
// sal=2000.0], Employee [id=8, name=杨, age=20, gebder=男, sal=2000.0]]
}
/**
* 4. 写XML写到新的文件中 1.创建Document对象 2.添加数据 3.生成XML文件
*/
@Test
public void test05() throws IOException {
// 定义一个集合
List<Employee> emps = new ArrayList<Employee>();
// 构造函数创建对象
Employee emp1 = new Employee(12, "yang", 50, "男", 2000);
Employee emp2 = new Employee(02, "c", 20, "男", 2000);
// 将对象放入到集合中
emps.add(emp1);
emps.add(emp2);
// 创建Document对象
Document doc = DocumentHelper.createDocument();
// 添加根节点
Element root = doc.addElement("list");
// 循环填入数据
for (Employee emp : emps) {
// 给根节点list下添加一个employee节点
Element employee = root.addElement("employee");
// 给employee节点下添加id属性,name,age,gender,salary元素节点
employee.addAttribute("id", emp.getId() + " ");
employee.addElement("name").addText(emp.getName());
employee.addElement("age").addText(emp.getAge() + " ");
employee.addElement("gender").addText(emp.getGebder());
employee.addElement("salsay").addText(emp.getSal() + " ");
}
// 把内存中的Document对象中的数据写到写到指定的xml文件中
// 方式一
// XMLWriter writer = new XMLWriter();
// OutputStream os = new FileOutputStream("newEmployee.xml");
// writer.setOutputStream(os);
// writer.write(doc);
// writer.close();
// 方式二
OutputFormat outformat = OutputFormat.createPrettyPrint();
outformat.setEncoding("UTF-8");
OutputStream os = new FileOutputStream("src/main/resources/employee.xml");
XMLWriter writer = new XMLWriter(os, outformat);
writer.write(doc);
writer.close();
}
DOM解析方式:(document Object Model文档对象模型),是w3c组织推荐的处理xml的一种方式,dom解析器在解析xml文档时,会把文档中的所有元素按照其出现的层次关系解析成一个Node对象(节点对象)。
优点:把xml文件在内存中构建树形结构,可以遍历和修改节点。
缺点:如果文件比较大,内存有压力,解析时间会比较长。
Dom解析不需要额外第三方jar包,jdk(jre)提供了若干api操作xml。
路径表达式,Xpath是一门在XML文档中查找信息的语言。Xpath可以用来在xml文档中对元素和属性进行遍历。由于我们单纯使用dom定位节点时,大部分时间需要一层一层的处理,有了xpath就解决了逐层遍历。他可以根据路径,属性,甚至是条件进行节点检索。
路径表达式
- 斜杠(/)作为路径的分隔符
- 导航到同样一个节点,有相对路径和绝对路径两种
绝对路径:必须从"/"起始,后面紧跟节点,比如:/list/employee
相对路径:以当前路径作为起始点,比如: employee/name
- "."表示当前节点
- ".."表示当前节点的父节点
- nodename(节点名称):表示该节点的所有子节点
- "/" 表示跟节点
- "//" 表示选择任意位置的某个节点
- "@" 表示选择某个属性
以下面xml的文档为例:
<?xml version="1.0" encoding="utf-8" ?>
<bookstore>
<book>
<title lang="eng">harry potter</title>
<price>39.9</price>
</book>
<book>
<title lang="eng">learning XML</title>
<price>59.9</price>
</book>
</bookstore>
谓语
谓语条件,就是对路径表达式的附加条件,所有的条件都写在[]中,表示对节点的进一步筛选,比如
通配符