1、schema约束简介
一个xml中可以有多个schema,用名称空间区分,相比于dtd约束,schema支持更多的类型,约束的更严格。schema符合xml的语法规范,有根节点,该根节点就是schema
2、schema快速入门
(1)、创建schema文件,后缀名为.xsd
(2)、看xml文件中有多少个元素,就写多少个<element>
(3)、分辨简单元素和复杂元素:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/1" xmlns:tns="http://www.example.org/1" elementFormDefault="qualified">
<element name="person">
<complexType>
<sequence>
<element name="name" type="string"></element>
<element name="age" type="string"></element>
</sequence>
</complexType>
</element>
</schema>
(4)、在xml文件中引入约束文件
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.example.org/1"
xsi:schemaLocation="http://www.example.org/1 1.xsd">
<name>zhangSan</name>
<age>20</age>
</person>
<sequence>:表示元素出现的顺序
把<sequence>换成<all>则表示元素只能出现一次,换成<choice>表示只能出现其中一个元素
3、sax解析原理
概念见xml学习笔记一中的xml的dom和sax两种解析技术
sax解析:事件驱动,边读边解析
在javax.xml.parsers包内有两个类:
SAXParser类:通过saxParserFactory.newSAXParser()得到实例
SAXParserFactory类:通过SAXParserFactory.newInstance()得到实例
4、使用jaxp的sax方式解析xml:
sax方式不能实现增删改操作,只能实现查询操作。
TestSax.java文件内容:
package cn.itcast.jaxsax;
import java.io.IOException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class TestSax {
public static void main(String[] args) throws Exception{
/*
* 1、创建解析器工厂
* 2、创建解析器
* 3、执行parse方法解析xml文件
* 4、创建一个类,继承DefaultHandler
* 5、重写handler中的三个方法
* */
//创建解析器工厂
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
//创建解析器
SAXParser saxParser = saxParserFactory.newSAXParser();
//执行parse方法解析xml文件
saxParser.parse("src/person.xml", new MyDefaultHandler());
}
}
//创建一个类,继承DefaultHandler
class MyDefaultHandler extends DefaultHandler{
//重写DefaultHandler的下述三个方法
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
// TODO Auto-generated method stub
System.out.println("start: " + qName);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// TODO Auto-generated method stub
System.out.println("text: " + new String(ch, start, length));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// TODO Auto-generated method stub
System.out.println("end: " + qName);
}
}
person.xml文件内容:
<?xml version="1.0" encoding="UTF-8"?>
<person>
<p1>
<name>ZhangSan</name>
<age>20</age>
</p1>
<p1>
<name>LiSi</name>
<age>21</age>
</p1>
</person>
5、使用dom4解析xml
dom4j是一个组织,针对xml解析,提供解析器dom4j,文档:https://dom4j.github.io/,API:https://dom4j.github.io/javadoc/1.6.1/
dom4j不是javaSE的一部分,需要在工程中导入dom4j的jar包:
在MyEclipse中右键点击工程文件夹,创建一个lib文件夹,
复制dom4j.jar到lib文件夹下,
右键dom4j.jar,点build path->add to buildPath,当出现奶瓶样符号的jar包时说明导入成功。
使用dom4j得到document:
import java.net.URL;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
public class Foo {
public Document parse(URL url) throws DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(url);
return document;
}
}
6、使用dom4j实现查询操作
查询所有name元素里面的值:
TestDom4j.java文件内容:
package cn.itcast.dom4j;
import java.util.List;
import javax.xml.parsers.SAXParserFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class TestDom4j {
public static void main(String[] args) throws Exception{
//创建解析器
SAXReader saxReader = new SAXReader();
//获取document
Document document = saxReader.read("src/person.xml");
//获取根节点
Element root = document.getRootElement();
//获得所有的p1标签
List<Element> p1List = root.elements();
//使用增强for循环遍历p1 list
for(Element p1 : p1List){
//获取name标签
Element name = p1.element("name");
//打印name中的值
System.out.println(name.getText());
}
}
}
person.xml文件内容:
<?xml version="1.0" encoding="UTF-8"?>
<person>
<p1>
<name>ZhangSan</name>
<age>20</age>
</p1>
<p1>
<name>LiSi</name>
<age>21</age>
</p1>
</person>
7、在第一个p1标签后添加新元素<sex>nv</sex>:
package cn.itcast.dom4j;
import java.io.FileOutputStream;
import java.util.List;
import javax.xml.parsers.SAXParserFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class TestDom4j {
public static void main(String[] args) throws Exception{
// selectAllName();
addSex();
}
private static void selectAllName() throws DocumentException {
//创建解析器
SAXReader saxReader = new SAXReader();
//获取document
Document document = saxReader.read("src/person.xml");
//获取根节点
Element root = document.getRootElement();
//获得所有的p1标签
List<Element> p1List = root.elements();
//使用增强for循环遍历p1 list
for(Element p1 : p1List){
//获取name标签
Element name = p1.element("name");
//打印name中的值
System.out.println(name.getText());
}
}
private static void addSex() throws Exception{
//创建解析器
SAXReader saxReader = new SAXReader();
//获取document
Document document = saxReader.read("src/person.xml");
//获取根节点
Element root = document.getRootElement();
//获得第一个p1标签
Element p1 = root.element("p1");
//在p1下添加元素
Element sex = p1.addElement("sex");
//在sex下添加文本
sex.addText("nv");
//回写操作
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/person.xml"), format);
xmlWriter.write(document);
xmlWriter.close();
}
}
8、使用dom4j支持XPATH的操作
可以直接获取某个元素,而不用像前文的一层一层的获取。
-第一种形式:/AA/DD/BB,一层一层的解析得到BB
-第二种形式://BB,只要名称为BB就得到
-第三种形式:/*,表示所有元素都得到
-第四种形式:BBB[1]表示第一个BBB元素,BBB[last()]表示最后一个BBB元素
-第五种形式://BBB[@id],只要元素BBB上有id属性则就得到
-第六种形式://BBB[@id='b1'],得到有属性id且属性值为b1的BBB元素
9、使用dom4j支持XPATH的具体操作
一、导入支持XPATH的dom4j的jar包:jaxen-1.1-beta-6.jar。
二、使用:
获取多个节点:selectNodes("xpath表达式");
获取单一节点:selectSingleNode("xpath表达式");
10、简单学生信息管理系统
student.xml文件内容:
<?xml version="1.0" encoding="UTF-8"?>
<student>
<stu>
<id>100</id>
<name>ZhangSan</name>
<age>21</age>
</stu>
<stu>
<id>101</id>
<name>LiSi</name>
<age>22</age>
</stu>
</student>
StuService.java文件内容:
package cn.itcast.service;
import java.io.FileOutputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.SAXWriter;
import org.dom4j.io.XMLWriter;
import cn.itcast.vo.*;
public class StuService {
//增加操作
public static void addStudent(Student student) throws Exception{
//创建解析器
SAXReader saxReader = new SAXReader();
//获取document
Document document = saxReader.read("src/student.xml");
//获取根节点student
Element root = document.getRootElement();
//在根节点上添加stu节点
Element stu = root.addElement("stu");
//在stu节点上依次添加id,name,age
Element id = stu.addElement("id");
Element name = stu.addElement("name");
Element age = stu.addElement("age");
//依次为id,name,age添加值
id.setText(student.getId());
name.setText(student.getName());
age.setText(student.getAge());
//回写操作
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/student.xml"), format);
xmlWriter.write(document);
xmlWriter.close();
}
//删除操作,根据学生的id删除
public static void delStudent(String delId) throws Exception{
//创建解析器
SAXReader saxReader = new SAXReader();
//获取document
Document document = saxReader.read("src/student.xml");
//获取根节点student
Element root = document.getRootElement();
//使用XPATH获取id节点list
List<Element> idList = root.selectNodes("//id");
//遍历id的list,获取每个id的值
for(Element id : idList){
//判断当前id的值与要删除的id值是否相同
if(id.getText().equals(delId)){
//若相同,则获取当前id父节点stu的父节点,然后利用其父节点将该stu节点删除
Element stu = id.getParent();
Element stuParent = stu.getParent();
stuParent.remove(stu);
}
}
//回写操作
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/student.xml"), format);
xmlWriter.write(document);
xmlWriter.close();
}
//查询操作,根据id查询
public static Student getStudent(String ID) throws Exception{
Student student = new Student();
//创建解析器
SAXReader saxReader = new SAXReader();
//获取document
Document document = saxReader.read("src/student.xml");
//获取根节点student
Element root = document.getRootElement();
//使用XPATH获取id节点list
List<Element> idList = root.selectNodes("//id");
//遍历id的list,获取每个id的值
for(Element id : idList){
//判断当前id的值与要删除的id值是否相同
if(id.getText().equals(ID)){
//若相同,则获取当前id父节点stu的父节点
Element stu = id.getParent();
//获取该stu的id,name,age
String getID = stu.elementText("id");
String getName = stu.elementText("name");
String getAge = stu.elementText("age");
student.setId(getID);
student.setName(getName);
student.setAge(getAge);
}
}
return student;
}
}
Student.java文件内容:
package cn.itcast.vo;
public class Student {
private String id;
private String name;
private String age;
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;
}
}
TestStu.java文件内容:
package cn.itcast.test;
import cn.itcast.vo.*;
import cn.itcast.service.*;
public class TestStu {
public static void main(String[] args) throws Exception {
// testAdd();
// testDel();
testGet();
}
public static void testAdd() throws Exception{
Student stu = new Student();
stu.setId("103");
stu.setName("WangWu");
stu.setAge("23");
StuService.addStudent(stu);
}
public static void testDel() throws Exception{
StuService.delStudent("103");
}
public static void testGet() throws Exception{
Student stu = StuService.getStudent("100");
System.out.println(stu.getName());
}
}