XML:扩展标记语言(Extensible Markup Languae)
是独立于软件和硬件的信息传输工具
- xml可以简化数据共享
- xml可以数据传输
- xml可以平台变更
xml的处理指令
version:xml的版本
encoding:xml的内容编码
xml文档里包含的是xml的元素
xml元素:指的是从开始标签直到结束标签的部分,元素里可以包含其他元素,元素也可以拥有其他属性.
比如:
<students>
<student id="1">
<name>张三</name>
<age>20</age>
<stuNo>S001</stuNo>
</student>
<student id="2">
<name>李四</name>
<age>30</age>
<stuNo>S002</stuNo>
</student>
</students>
- students,student,name,age,stuNo这些都叫元素标签,也可以叫元素节点,元素对象,
- id是某个元素的节点的属性,也可以叫属性节点,也叫属性对象
-
张三,20,S001等这样的数据叫做值,也可以叫做文本节点和文本对象
- 元素节点:一般用来表达某种语义
- 属性节点:一般用来修饰和补充元素节点
- 文本节点:一般用来表达指定语义的值
xml需要注意的几个问题:
- xml元素节点,必须成对出现,且开始标签和结束标签名必须一样
- xml属性节点的值需要用引号括起来,可以是双引号也可以,是单引号,如果属性值本身包含双引,则需要用单引包围他
比如:
<student name='二"狗"子'></student>
- xml对大小写敏感,区分大小写
- xml中要求,必须有跟元素节点,并且跟节点只有一个根节点包含所有其他子节点(元素,文本,属性)
- 所有元素节点必须正确嵌套
- 实体引用:xml中有若干符号,是跟xml有冲突的,所以需要用别名代替
比如: | 实体引用 | 字符 | 说明 | | :—— |:— | :— | | < | < | 小于 | | > | > | 大于 | | & | & | 与 | | &aops; | ‘ | 单引号 | | " | “ | 双引号 |
<name>1<2</name>
<desc>这个是一个"描述"文本</desc>
- CDATA段,段中的内容当成一个文本块来看待
语法:
<![CDATA[文本内容]]>
比如:
<desc>
<![CDATA[
<说明>
CDATA段中的所有内容太都当成一个文本块来看待
如果有类似的元素节点也不会当成xml看待
只是普通的文本
</说明>
]]>
</desc>
xml解析:
- SAX解析方式:(simple api for xml)是一种xml解析的替代方法,想对比DOM机械,sax解析是一种速度快,更有效的方法,因为他是逐行扫描xml文档,一边扫描,一边解析,而且相对于dom解析,sax可以在解析文档的任意时刻停止解析
- 优点:解析可以立即开始,速度快,没有内存压力
- 缺点:不能对节点做修改
- DOM解析方式:(document Object Model文档对象模型)是w3c组织推荐的处理xml的一种方式,dom解析器在解析xml文档时,会把文档中的所有元素按照其出现的层次关系,解析成一个Node对象(节点对象)
- 优点:把xml文件在内存中构建树形结构,可以遍历和修改节点
- 缺点:如果文件比较大,内存有压力,解析时间会比较长
- sax解析必须借助第三方工具dom4j,工具中提供若干jar包,jar包中提供了若干api,来解析xml,dom4j是一个非常优秀的解析xml框架,也是一个开源的框架
- Dom解析不需要额外第三方jar包,jdk(jre)提供了若干api操作xml
SAX api:
- Element getRootElement(); Document类
获取根节点,以备获取跟节点后面的节点对象 - List elements(); Element类
获取当前节点下的所有元素节点,返回结果是List集合 - Attribute attribute(String attributeName); Element类
获取当前节点的某一个属性名对应的属性对象,返回值是Attribute类的对象 - String getValue; Attribute类
获取当前属性对象中的属性值 - Element element(String elementName); Element类
获取当前元素节点下的 指定元素节点名称的 元素对象 - String getText(); Element类
获取当前元素节点里的文本节点的值 - String elementText(String elementName); Element类
获取当前元素节点下的指定元素节点名称的节点里的文本节点的值
写xml节点到xml文件:
- 创建文档对象
Document doc =DocumentHelper.CreateDocument();
获取文档对象
Document doc=new SAXReader().read("xxx.xml");
- 定位节点 并添加
- 把document对象写到xml中
- 方式一:
XMLWriter writer=new XMLWriter();
OutPutStream os=new FileOutputStream("src/resources/new.xml");
writer.setOutputStream(os);
//把内存中的数据写入到new.xml文件中
writer.write(document);
writer.close();
- 方式二:
OutputFormat outformat=OutputFormat.createPrettyPrint();
outformat.setEncoding("UTF-8");
OutputStream os=new FileOutputStream("bin/resource/employee.xml");
XMLWriter writer=new XMLWriter(os,outformat);
//把内存中的数据写入employee.xml中
writer.write(document);
write.close();
sax方式写入xml常用api:
- Element addElement(String elementNodeName); Element类
在当前元素节点里,添加一个新元素节点,节点的名字elementNodeName - Element addAttribute(String propertyName,String propertyValue);
Element类在当前的节点上添加属性,属性的名称propertyName属性的值 propertyValue - Element addText(String text); Element类
给当前节点添加文本节点
XPath:路径表达式
xpath是一门在xml文档中查找信息的语言,xpath可用来在xml文档中对元素或属性进行遍历
有了xpath就解决了逐层遍历
xpath是用网络路径表达式在xml文档中进行导航(快速查找)
xpath包含一个标准函数库
xpath是xslt中的主要元素
xpath是w3c标准
路径表达式:
- 斜杠(/)作为路径的分隔符
- 导航到同样一个节点,有相对路径和绝对路径两种绝对路径:
必须从”/”起始,后面紧跟节点
比如:/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元素
要想使用xpath必须引入第三方的jar包
jaxen-xx-xx.jar
使用xpath的api
List SelectNodes(String xpath);
根据xpath的参数获取xpath指定节点的信息
例子
xpath用法
Employee.java
public class Employee {
private int id;
private String name;
private int age;
private String gender;
private double salary;
public Employee(){}
public Employee(int id, String name, int age, String gender, double 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 double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + ", salary=" + salary
+ "]";
}
}
Employee.xml
<?xml version="1.0" encoding="UTF-8"?>
<list>
<employee id="1">
<name>张三</name>
<age>20</age>
<gender>男</gender>
<salary>5000</salary>
</employee>
<employee id="2">
<name>李四</name>
<age>21</age>
<gender>男</gender>
<salary>5200</salary>
</employee>
<employee id="3">
<name>王五</name>
<age>20</age>
<gender>男</gender>
<salary>50000</salary>
</employee>
<employee id="4">
<name>赵六</name>
<age>20</age>
<gender>男</gender>
<salary>10000</salary>
</employee>
<employee id="5">
<name>田七</name>
<age>20</age>
<gender>男</gender>
<salary>20000</salary>
</employee>
</list>
Demo2.java
/**
* 此类现实xpath用法
* @author PC
*
*/
public class Demo2 {
@Test
public void test1()throws Exception{
SAXReader reader=new SAXReader();
//通过Demo的Class所在位置来定位到employee.xml
InputStream is=Demo2.class.getClassLoader().getResourceAsStream("resources/employee.xml");
Document doc=reader.read(is);
//xpath用法
List<Element> emps=doc.selectNodes("/list/employee[@id='3']");
for(Element emp:emps){
System.out.println("name="+emp.elementText("name"));
}
}
}
public class Demo1 {
/**
* 获取文件的路径为相对路径
* 且当前路径是项目的根目录
* @param fileName
* @return
* @throws Exception
*/
private Document readXML1(String fileName) throws Exception{
Document doc=null;
//创建一个SAXReader解析器
SAXReader xmlReader=new SAXReader();
doc=xmlReader.read(fileName);
return doc;
}
/**
* 文件是从类路径中获取的
* @param fileName
* @return
* @throws Exception
*/
private Document readXML2(String fileName) throws Exception{
Document doc=null;
//创建一个SAXReader解析器
SAXReader xmlReader=new SAXReader();
//从类路径中获取文件路径
InputStream is=Demo1.class.getClassLoader().getResourceAsStream(fileName);
doc=xmlReader.read(is);
return doc;
}
@Test
public void test1(){
try {
Document doc=this.readXML1("bin/resources/employee.xml");
System.out.println(doc);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Test
public void test2(){
try {
Document doc=this.readXML2("resources/employee.xml");
System.out.println(doc);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 获取跟节点
*/
@Test
public void test3(){
try {
Document doc=this.readXML2("resources/employee.xml");
// System.out.println(doc);
//从doc对象中取出根节点
Element root=doc.getRootElement();
System.out.println(root.getName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 根据根节点,获取根节点下所有儿子的元素节点
*/
@Test
public void test4(){
List<Employee> emps=new ArrayList<Employee>();
try {
Document doc=this.readXML2("resources/employee.xml");
// System.out.println(doc);
//从doc对象中取出根节点
Element root=doc.getRootElement();
// System.out.println(root.getName());
//获取根节点下的所有儿子的元素节点
List<Element> employees=root.elements();
for(Element employee:employees){
//属性id
int id=Integer.parseInt(employee.attributeValue("id"));
//获取name
String name=employee.elementText("name");
//获取age
int age=Integer.parseInt(employee.element("age").getText());
//获取性别
String gender=employee.elementText("gender");
//获取薪水
double salary=Double.parseDouble(employee.elementText("salary"));
Employee emp=new Employee(id,name,age,gender,salary);
emps.add(emp);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(emps);
}
/**
* 根据跟节点
* 获取根节点下的所有的儿子节点
* 用迭代器实现的
*/
@Test
public void test5(){
List<Employee> emps=new ArrayList<Employee>();
try {
Document doc=this.readXML2("resources/employee.xml");
// System.out.println(doc);
//从doc对象中取出根节点
Element root=doc.getRootElement();
// System.out.println(root.getName());
//获取根节点下的所有儿子的元素节点
Iterator<Element> employees=root.elementIterator();
while(employees.hasNext()){
Element employee=employees.next();
//属性id
int id=Integer.parseInt(employee.attributeValue("id"));
//获取name
String name=employee.elementText("name");
//获取age
int age=Integer.parseInt(employee.element("age").getText());
//获取性别
String gender=employee.elementText("gender");
//获取薪水
double salary=Double.parseDouble(employee.elementText("salary"));
Employee emp=new Employee(id,name,age,gender,salary);
emps.add(emp);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(emps);
}
/**
* 写xml
* 1.创建Document
* 2.添加数据
* 3.生成xml
* @throws Exception
*/
@Test
public void test6() throws Exception{
List<Employee> emps=new ArrayList<Employee>();
//构建要添加的Employee的数据
Employee emp1=new Employee(6,"aa",20,"男",2000);
Employee emp2=new Employee(7,"bb",20,"男",2000);
Employee emp3=new Employee(8,"cc",20,"男",2000);
Employee emp4=new Employee(9,"dd",20,"男",2000);
Employee emp5=new Employee(10,"ee",20,"男",2000);
Employee emp6=new Employee(11,"ff",20,"男",2000);
emps.add(emp1);
emps.add(emp2);
emps.add(emp3);
emps.add(emp4);
emps.add(emp5);
emps.add(emp6);
//1.创建Document对象
Document doc=DocumentHelper.createDocument();
//2.添加根节点
Element root = doc.addElement("list");
//3.循环添入数据
for(Employee emp:emps){
//给根节点下添加了一个Employee节点
Element employee=root.addElement("employee");
//给Employee节点添加信息
employee.addAttribute("id",emp.getId()+" ");
employee.addElement("name").addText(emp.getName());
employee.addElement("age").addText(emp.getAge()+" ");
employee.addElement("gender").addText(emp.getGender());
employee.addElement("salary").addText(emp.getSalary()+" ");
}
//把内存中构建完的xml文档写入xml
XMLWriter writer=new XMLWriter();
OutputStream os=new FileOutputStream("src/resources/newemployee.xml");
writer.setOutputStream(os);
writer.write(doc);
writer.close();
}
/**
* 写xml
* 1.创建Document
* 2.添加数据
* 3.生成xml
* @throws Exception
*/
@Test
public void test7() throws Exception{
List<Employee> emps=new ArrayList<Employee>();
//构建要添加的Employee的数据
Employee emp1=new Employee(6,"aa",20,"男",2000);
Employee emp2=new Employee(7,"bb",20,"男",2000);
Employee emp3=new Employee(8,"cc",20,"男",2000);
Employee emp4=new Employee(9,"dd",20,"男",2000);
Employee emp5=new Employee(10,"ee",20,"男",2000);
Employee emp6=new Employee(11,"ff",20,"男",2000);
emps.add(emp1);
emps.add(emp2);
emps.add(emp3);
emps.add(emp4);
emps.add(emp5);
emps.add(emp6);
//1.创建Document对象
Document doc=this.readXML2("resources/employee.xml");
//2.添加根节点
Element root = doc.getRootElement();
//3.循环添入数据
for(Employee emp:emps){
//给根节点下添加了一个Employee节点
Element employee=root.addElement("employee");
//给Employee节点添加信息
employee.addAttribute("id",emp.getId()+"");
employee.addElement("name").addText(emp.getName()+"");
employee.addElement("age").addText(emp.getAge()+"");
employee.addElement("gender").addText(emp.getGender()+"");
employee.addElement("salary").addText(emp.getSalary()+"");
}
//把内存中构建完的xml文档写入xml
XMLWriter writer=new XMLWriter();
OutputStream os=new FileOutputStream("src/resources/employee.xml");
writer.setOutputStream(os);
writer.write(doc);
writer.close();
}
}