一、XML语法
1.1、XML用途
XML指可扩展标记语言(Extensible Markup Language),是独立于软件和硬件的信息传输工具。XML应用于Web开发的许多方面,常用于简化数据的存储、传输和共享。
1.2、XML基本语法
1.2.1 XML处理指令
XML处理指令,简称PI(processing instruction),处理指令用来指示解析引擎如何解析XML文档内容。
<?xml version="1.0" encoding="UTF-8"?>
在XML中,所有的处理指令都以<?开始,?>结束。<?后面紧跟的是处理指令的名称。XML处理指令要求指定一个version属性。并允许指定可选的standalone和encoding,其中standalone是指是否允许使用外部声明,可设置为yes或no。yes是指定不使用外部声明,no为使用。encoding是指作者使用的字符编码格式,有UTF-8,GBK,gb2312等。
1.2.2 元素和属性
XML文档包含XML元素。XML元素指的是从(且包括)开始标签直到(且包括)结束标签的部分。元素可包含其他元素、文本或者两者的混合物。元素也可以拥有属性。
XML元素可以在开始标签中包含属性,属性(Attribute)提供关于元素的额外(附加)信息。属性通常提供不属于数据组成部分的信息,但是对需要处理这个元素的应用程序来说却很重要。
XML属性必须加引号,属性值必须被引号包围,不过单引号和双引号均可使用。如果属性值本身包含引号,那么有必要使用单引号包围它,或者可以使用实体引用。
<datasource id="db_oracle">
...
</datasource>
1.2.3 大小写敏感
XML对大小写是敏感的,这一点不像HTML。
1.2.4 元素必须有关闭标签
XML要求每个元素必须由起始标签和关闭标签组成。关闭标签与起始标签的名字相同,写法上多一个”/”。
另外,XML要求所有元素必须正确的嵌套。
1.2.5 必须有根元素
XML要求必须有根元素,所谓根元素就是不被其他元素包围。并且根元素只能有一个。
1.2.6 实体引用
实体可以是常用的短语,键盘字符,文件,数据库记录或任何包含数据的项。在XML中,有时实体内包含一些字符,如& < > ” ‘等。这些均需要对其进行转义,否则会对XML解释器生成错误。
实体引用 | 字符 | 说明 |
---|---|---|
< ; | < | 小于 |
> ; | > | 大于 |
& ; | & | 与字符(和字符) |
&apos ; | ‘ | 单引号 |
" ; | “ | 双引号 |
(上表中实体引用字段,分号和前一个字符间实际应无空格,这里为显示,加了一空格。)
1.2.7 CDATA段
格式:<![CDATA[文本内容]]>,特殊标签中的实体引用都被忽略,所有内容被当成一整块文本数据对待。
二、XML解析
2.1 XML解析方式
2.1.1 SAX解析方式
SAX(simple API for XML)是一种XML解析的替代方法。相比于DOM,SAX是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOM,SAX可以在解析文档的任意时刻停止解析。
优点:解析可以立即开始,速度快,没有内存压力。
缺点:不能对节点做修改。
2.1.2 DOM解析方式
DOM(Document Object Model),即文档对象模型,是W3C组织推荐的处理XML的一种方式。
DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
优点:把XML文件在内存中构造树形结构,可以遍历和修改节点。
缺点:如果文件比较大,内存有压力,解析的时间会比较长。
2.2 读XML
2.2.1 SAXReader读取XML文档
可以创建SAXRead而对象来读取XML文档,而使用SAXReader需要导入dom4j的jar包,这里用1.6.1版本。
dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的。dom4j是一个非常优秀Java XML API,具有性能优异、功能强大和易用的特点,同时它也是一个开放源代码的软件。
2.2.2 Document的getRootElement方法
Document对象是一颗文档树的根,可为我们提供对文档数据最初(或最顶层)的访问入口。
Element对象表示XML文档中的元素。元素可包含属性、其他元素或文本。如果元素含有文本,则在文本节点中表示该文本。
Element getRootElement()用于获取根元素。
Attribute对象用于描述一个元素中的某个属性信息。
关于Element和Attribute的一些方法就不再赘述啦,直接在程序里面说明。
后面的代码都需要建一个maven工程,要先下载安装maven,并配置好,并导入需要的jar包,关于maven的使用这里也不再赘述啦。
package day12;
/**
* 该类用于表示xml文档中的一个员工信息
* @author Administrator
*
*/
public class Emp {
private int id;
private String name;
private int age;
private String gender;
private int salary;
public Emp() {
}
public Emp(int id, String name, int age, String gender, int salary) {
super();
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String toString() {
return id+","+name+","+age+","+gender+","+salary;
}
}
package day12;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* 使用DOM解析xml文档
* @author Administrator
*
*/
public class ParseXmlDemo {
public static void main(String[] args) {
/*
*解析emplist.xml文档,将所有的员工信息读取出来并转换为若干Emp实例,
*存入一个List集合中。
*
*解析XML的流程:
*1、创建SAXReader;
*2、使用SAXReader读取XML文档并返回Document对象;
* 这一步就是DOM解析耗时耗资源的体现,因为DOM会将XML文档全部读取并
* 以一个Document对象形式存于内存。
* Document对象用于描述解析的XML文档内容。
*3、根据Document对象获取根元素;
*4、按照xml的结构从根元素中开始逐级获取子元素以达到遍历xml的目的。
*/
try {
SAXReader reader = new SAXReader();
Document doc = reader.read(new FileInputStream("emplist.xml"));
/*
* Element的每一个实例用于表示xml文档中的一个元素(一对标签)
* 这里获取的相当于是emplist.xml文档中的<list>标签
*/
Element root = doc.getRootElement();
/*
* Element提供了获取元素的相关方法:
*
* List elements()
* 获取当前标签下的所有子标签
*
* List elements(String name)
* 获取当前标签下所有同名子标签
*
* Element element(String name)
* 获取指定名字的子标签
*
* Attribute attribute(String name)
* 获取指定名字的属性
*
* String getName()
* 获取当前标签的名字
*
*String getText()
*获取当前标签中的文本(前标签和后标签中间的文本信息,前提是确实为文本而
*不是子标签)
*/
List<Emp> emplist = new ArrayList<Emp>();
/*
* 获取根标签<list>下面的所有子标签<emp>
*/
List<Element> elements = root.elements();
/*
* 遍历所有<emp>标签并解析出该员工相关信息并以一个Emp实例
* 保存,然后将其存入empList集合
*/
for(Element empEle:elements) {
//获取名字
Element nameEle = empEle.element("name");
String name = nameEle.getTextTrim();
//获取年龄
int age = Integer.parseInt(empEle.elementTextTrim("age"));
//获取性别
String gender = empEle.elementTextTrim("gender");
//获取薪资
int salary = Integer.parseInt(empEle.elementTextTrim("salary"));
/*
* 获取emp标签中的id属性
* Attribute的每一个实例用于表示一个属性信息,常用方法:
* String getName()获取当前属性名
* String getValue()获取当前属性值
*/
Attribute attr = empEle.attribute("id");
int id = Integer.parseInt(attr.getValue());
Emp emp = new Emp(id,name,age,gender,salary);
emplist.add(emp);
}
System.out.println("解析完毕!");
System.out.println("共"+emplist.size()+"个员工!");
for (Emp emp:emplist) {
System.out.println(emp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.3 写XML
通过dom4j写出XML的第一步是创建文档对象Documemt。创建Document对象的方式是通过DocumentHelper的静态方法createDocument来获取的。
static Document createDocument(),创建一个Document对象并返回。
创建好Document对象后,先添加根元素,然后再向根元素中追加新的子元素,并添加属性或文本等,最后写出生成XML文档。
package day12;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
/**
* 使用DOM生成XML文档
* @author Administrator
*
*/
public class WriteXmlDemo {
public static void main(String[] args) {
List<Emp> emplist = new ArrayList<Emp>();
emplist.add(new Emp(1,"张三",22,"男",3000));
emplist.add(new Emp(2,"李四",23,"女",4000));
emplist.add(new Emp(3,"王五",24,"男",5000));
emplist.add(new Emp(4,"赵六",25,"女",6000));
emplist.add(new Emp(5,"钱七",26,"男",7000));
/*
* 将emplist集合中的员工信息保存到myemp.xml文档中。
*
* 写出XML文档的大致步骤:
* 1、创建一个Docunment对象表示一个空白的xml文档。
* 2、向Document对象中添加根元素。
* 3、按照应当生成的xml文档的格式逐级向根元素中添加子元素以形成xml文档格式。
* 4、创建XmlWriter
* 5、通过XmlWriter将Document写出。
*/
XMLWriter writer = null;
try {
//1
Document document = DocumentHelper.createDocument();
/*
* 2、添加根标签<list>
* Document提供了添加根元素的方法
*
* Element addElement(String name)
* 该方法可以向当前文档中添加给定名字的根元素,并将添加进去的该元素
* 以一个Element实例返回,以便于对该元素继续操作。
* 需要注意,该方法只能调用一次,因为一个文档中只能有一个根元素。
*/
Element root = document.addElement("list");
/*
* 将empList集合中的每个员工信息以一个<emp>标签的形式保存到<list>标签中
*/
for (Emp emp:emplist) {
/*
* Element提供了相关方法:
*
* Element addElement(String name)
* 向当前标签中添加给定名字的子标签并将其返回,以便继续操作。
*
* Element addText(String text)
* 向当前标签中添加文本信息,返回值为当前标签。
*
* Element addAttribute(String name,String value)
* 向当前标签中添加属性,返回值为当前标签。
*/
//向根标签<list>中添加子标签<emp>
Element empEle = root.addElement("emp");
//向<emp>标签中添加<name>标签
Element nameEle = empEle.addElement("name");
nameEle.addText(emp.getName());
empEle.addElement("age").addText(emp.getAge()+"");
empEle.addElement("gender").addText(emp.getGender());
empEle.addElement("salary").addText(emp.getSalary()+"");
//添加属性
empEle.addAttribute("id", emp.getId()+"");
}
FileOutputStream fos = new FileOutputStream("myemp.xml");
writer = new XMLWriter(fos,OutputFormat.createPrettyPrint());
writer.write(document);
System.out.println("写出完毕!");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2.4 XPath
2.4.1 路径表达式
XPath是一门在XML文档中查找信息的语言。XPath可用来在XML文档中对元素和属性进行遍历。
由于我们单纯使用DOM定位节点时,大部分时间需要一层一层的处理,如果有了XPath,定位节点将变得很轻松。他可以根据路径、属性,甚至是条件进行节点的检索。
XPath使用路径表达式在XML文档中进行导航。
XPath包含一个标准函数库,XPath是XSLT中的主要元素,XPath是一个W3C标准。
斜杠(/)作为路径内部的分割符。
同一个节点有绝对路径和相对路径两种写法,绝对路径必须用“/”起首,后面紧跟根节点;相对路径则不适用“/”起首。“.”表示当前节点,“..”表示当前节点的父节点。
nodename(节点名称):表示选择该节点的所有子节点。
“/”:表示选择根节点。
“//”:表示选择任意位置的某个节点。
“@”:表示选择某个属性。
2.4.2 谓语条件
谓语条件,就是对路径表达式的附加条件。所有的条件,都写在方括号”[]”中,表示对节点进行进一步的帅选。
/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子元素。
/bookstore/book[price>35.00]:表示选择bookstore的book子元素,且被选中的book元素的price子元素值必须大于35。
/bookstore/book[price>35.00]/title:表示在上例结果集中,选择title子元素。
/bookstore/book/price[.>35.00]:表示选择值大于35的“/bookstore/book”的price子元素。
2.4.3 通配符
“*”表示匹配任何元素节点。
“@”表示匹配任何属性值。
node()表示匹配任何类型的节点。
/bookstore/*:鄙视选择bookstore的所有元素子节点。
//title[@*]:表示选择所有带有属性的title元素。
2.4.4 Dom4j对XPath的支持
采用XPath查找需要导入jaxen的jar包,我们用的是1.1.4的版本。
Document提供了一个对XPath检索的方法:List selectNodes(String XPath),传入XPath路径,获取相应的信息。
package day12;
import java.io.FileInputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* 使用XPath检索XML数据
* @author Administrator
*
*/
public class XPathDemo {
public static void main(String[] args) {
try {
SAXReader reader = new SAXReader();
Document doc = reader.read(new FileInputStream("myemp.xml"));
/*
* Document支持使用xpath检索数据,前提是必须引入jaxen这个jar包
*/
String xpath="/list/emp/name";
List<Element> list = doc.selectNodes(xpath);
for (Element ele:list) {
System.out.println(ele.getName() + ":" + ele.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}