文章目录
- 前言
- 1、XML解析
- 1.1、SAX
- 1.2、DOM
- 1.3、XPath
前言
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>
1、XML解析
1.1、SAX
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/");
System.out.println(document1);
// 2.从类路径下获取XML文件
InputStream is = TestAnnotationClass.class.getClassLoader().getResourceAsStream("");
Document document2 = sax.read(is);
System.out.println(document2);
// 结果
// org.@18ef96 [Document: name src/main/resources/]
// org.@769c9116 [Document: name null]
}
/**
* 2. 用SAX解析XML,获取文档的根节点对象
*/
@Test
public void test03() throws DocumentException {
SAXReader sax = new SAXReader();
InputStream is = TestAnnotationClass.class.getClassLoader().getResourceAsStream("");
Document document = sax.read(is);
// 从文件对象中获取文档的根节点
Element root = document.getRootElement();
System.out.println(root);
// 结果
// org.@6956de9 [Element: <list attributes: []/>]
}
/**
* 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("");
// 获取文档对象
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();
// 添加根节点 <List></List>
Element root = doc.addElement("list");
// 循环填入数据 <List><employee></employee></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("");
// (os);
// (doc);
// ();
// 方式二
OutputFormat outformat = OutputFormat.createPrettyPrint();
outformat.setEncoding("UTF-8");
OutputStream os = new FileOutputStream("src/main/resources/");
XMLWriter writer = new XMLWriter(os, outformat);
writer.write(doc);
writer.close();
}
1.2、DOM
DOM解析方式:(document Object Model文档对象模型),是w3c组织推荐的处理xml的一种方式,dom解析器在解析xml文档时,会把文档中的所有元素按照其出现的层次关系解析成一个Node对象(节点对象)。
优点:把xml文件在内存中构建树形结构,可以遍历和修改节点。
缺点:如果文件比较大,内存有压力,解析时间会比较长。
Dom解析不需要额外第三方jar包,jdk(jre)提供了若干api操作xml。
1.3、XPath
路径表达式,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>
- /bookstore 选取跟节点bookstore,这是绝对路径。
- bookstore/book 选取所有属于bookstore的子元素book元素,这是相对路径。
- //book 选取所有book子元素,而不管他们在文档中的位置。
- bookstore//book 选取所有属于bookstore元素的后代的,book的元素而不管他们位于bookstore之下什么位置。
- //@lang 选取所有名为lang的属性
谓语
谓语条件,就是对路径表达式的附加条件,所有的条件都写在[]中,表示对节点的进一步筛选,比如
- /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’] 表示所有具有lang属相且值等于eng的title节点。
- //bookstore/book[price] 表示选择bookstore的book子元素且被选中的book子元素必须带有price子元素。
- /booksstore/book[price>35.0] 表示选择bookstore的book子元素,且选中的book子元素的price的子元素值必须大于35.0。
- /bookstore/book[price>35.0]/title 表示在上面的例子结果中选择title子元素。
- /bookstore/book/price[.>35.0] 表示选择值大于35.0的/bookstore/book的price子元素。
通配符
- “*” 表示匹配任何元素节点。
- @ 表示匹配任何属性值。
- node() 表示匹配任何类型的节点。
- //* 选择文档中的所有元素节点。
- /* /* 表示选择所有第二层的元素节点。
- /bookstore/* 表示选择bookstore的所有元素子节点。
- //title[@*] 表示选择所有带有属性的title元素