schema约束
- schema符合xml的语法,xml语句。
- 一个xml中可以有多个schema,多个schema使用名称空间(类似于java的包)区分。
- schema里面支持更多的数据类型。
- schema语法更加复杂,schema目前不能替代dtd。
schema的快速入门
- schema文件用w3c提供的属性和标签来约束xml文件
创建一个schema文件
根节点
<schema>
<schema>
的属性- xmlns=”http://www.w3.org/2001/XMLSchema”
表示当前xml文件是一个约束文件 targetNamespace=”http://www.itcast.cn/20151111”
使用schema约束文件时,直接通过这个地址引入约束文件elementFormDefault=”qualified”
- xmlns=”http://www.w3.org/2001/XMLSchema”
- 步骤
- 看xml有多少个元素
<element>
- 看简单元素和复杂元素
- 复杂元素:
- 简单元素:写在复杂元素内
- 在被约束文件里面引入约束文件
- 看xml有多少个元素
// 复杂元素:
<element name="元素名">
<complexType>
<sequence>
子元素
</sequence>
</complexType>
</element>
// 简单元素:写在复杂元素内
<sequence>
<element name="name" type="string"></element>
<element name="age" type="int"></element>
</sequence>
// 在被约束文件里面引入约束文件
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.itcast.cn/20151111" xsi:schemaLocation="http://www.itcast.cn/20151111 1.xsd">
// 表示xml是一个被约束文件
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
// 是约束文档里面的targetNamespace
xmlns="http://www.itcast.cn/20151111"
// targetNamespace 空格 约束文件的路径
xsi:schemaLocation="http://www.itcast.cn/20151111 1.xsd">
<sequence>
:表示元素出现的顺序<all>
:元素只能出现一次<choice>
:元素只能出现其中的一个<elment name="xxx" maxOccurs="unbounded">
:表示元素出现的次数<any></any>
:表示任意元素- 可以约束属性:写在复杂元素里面,写在
</complexType>
之前
// name:属性名称
// type:属性类型
// use:属性是否必须出现
<attribute name="id1" type="int" use="required"></attribute>
sax解析的原理
- sax方式:事件驱动,边读边解析
- 在javax.xml.parser包里面
- SAXParser:此类的实例可以从SAXParserFactory.newSAXParser()方法获取
- parese(File f, DefaltHandler dh):第一个参数:xml路径;第二个参数:事件处理器
- SAXParserFactory:实例 newInstance()方法得到
- SAXParser:此类的实例可以从SAXParserFactory.newSAXParser()方法获取
- Sax执行过程
- 当解析到开始标签时候,自动执行startElement方法
- 当解析到文本时候,自动执行characters方法
- 当解析到结束标签时候,自动执行endElement方法
使用jaxp的sax方式解析xml
sax方式不能实现增删改操作,能能做查询操作。
- 打印整个文档
- 执行parse方法,第一个参数是xml路径;第二个参数是时间处理器,创建一个类,继承时间处理器的类,重写里面的三个方法
- 获取所有name元素的值
- 定义一个成员变量 falg=false
- 判断开始方法是否是name元素,如果是name元素,把flag值设置为true
- 如果flag是true,在characters方法里打印内容
- 当执行到结束方法时,把flag设置成false
- 获取第一个name元素的值
- 定义一个成员变量index = 1
- 在结束方法中 index++;
- 打印第一个name的值,在characters方法里判断:flag=true且index=1
package cn.itcast.jaxpsax;
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创建一个继承DefaultHandler的类 4.执行parse方法
*/
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
saxParser.parse("src/p1.xml", new Default1());
saxParser.parse("src/p1.xml", new Default2());
saxParser.parse("src/p1.xml", new Default3());
}
}
class Default1 extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.print("<" + qName + ">");
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.print(new String(ch, start, length));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.print("</" + qName + ">");
}
}
class Default2 extends DefaultHandler {
private boolean flag = false;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("name".equals(qName)) {
flag = true;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (flag == true) {
System.out.println(new String(ch, start, length));
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
flag = false;
}
}
class Default3 extends DefaultHandler {
private boolean flag = false;
private int index = 1;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("name".equals(qName)) {
flag = true;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (flag == true && index == 1) {
System.out.println(new String(ch, start, length));
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
flag = false;
if ("name".equals(qName)) {
index++;
}
}
}
使用dom4j解析xml
- dom4j不是javase的一部分,需要导入dom4j的jar包
- 得到document
SAXReader reader = new SAXReader();
Document document = reader.read(url);
- document的父接口是Node
- 如果在document里面找不到想要的方法,到Node里面去找
- document里面的方法 getRootElement():获取根节点 返回Element
- Element也是一个接口,父接口是Node
- getParent():获取父节点
- addElement():添加标签
使用dom4j查询xml
// src/p1.xml
<?xml version="1.0" encoding="UTF-8"?>
<person>
<p1 id1="AAA">
<name>zhangsan</name>
<age>30</age>
</p1>
<p1>
<name>lisi</name>
<age>30</age>
</p1>
</person>
- 查询所有name元素里面的值
- 创建解析器
- 得到document
- 得到根节点 getRootElement()
- 得到所有的p1标签
- elements(“p1”) 返回list集合
- 遍历list得到每一个p1
- element(qname):获取标签下第一个子标签
- elements(qname):获取标签下所有子标签(一层)
- elments():获取标签下所有一层子标签
- 得到name
- 在p1下执行element(“name”)
- 得到name里面的值
- getText()
// 查询xml里面所有的name值
public static void selectAllName() throws Exception {
/*
* 1.创建解析器
* 2.得到document
* 3.得到根节点 getRootElement()
* 4.得到所有的p1标签
* 5.得到name
* 6.得到name里面的值
*/
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("src/p1.xml");
Element root = document.getRootElement();
List<Element> list = root.elements("p1");
for (Element element : list) {
Element name = element.element("name");
String s = name.getText();
System.out.println(s);
}
}
- 查询第一个name元素的值
- 创建解析器
- 得到document
- 得到根节点 getRootElement()
- 得到第一个p1标签
- element(“p1”)
- 得到name
- element(“name”)
- 得到name里面的值
- getText()
// 获取到第一个name元素里面的值
public static void selectSinName() throws Exception {
/*
* 1.创建解析器
* 2.得到document
* 3.得到根节点 getRootElement()
* 4.得到第一个p1标签
* 5.得到name
* 6.得到name里面的值
*/
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("src/p1.xml");
Element root = document.getRootElement();
Element p1 = root.element("p1");
Element name = p1.element("name");
String s = name.getText();
System.out.println(s);
}
- 查询第二个name元素的值
- 创建解析器
- 得到document
- 得到根节点
- 得到所有的p1标签 返回list集合
- 得到第二个p 使用下标得到
- 得到第二个name
- 得到name的值
// 获取到第二个name元素里面的值
public static void selectSecName() throws Exception {
/*
* 1.创建解析器
* 2.得到document
* 3.得到根节点 getRootElement()
* 4.得到所有p1
* 5.得到第二个p1
* 6.得到name里面的值
*/
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("src/p1.xml");
Element root = document.getRootElement();
List<Element> list = root.elements("p1");
Element p2 = list.get(1);
Element name = p2.element("name");
String s = name.getText();
System.out.println(s);
}
使用dom4j实现添加操作
- 在第一个p1标签末尾添加一个元素
<sex>nv</sex>
- 创建解析器
- 得到document
- 得到根节点
- 得到第一个p1
- 在p1下添加元素
- 在添加完成之后的元素下添加文本
- 回写xml
- 格式化类 OutputFormat 使用类方法createPrettyPrint()
- 使用类XMLWriter,传递两个参数
- new FileOutputStream(“xml的路径”)
- 格式化类
// 在第一个p1标签末尾添加一个元素<sex>nv</sex>
public static void addSex() throws Exception {
/*
* 1.创建解析器
* 2.得到document
* 3.得到根节点 getRootElement()
* 4.获取第一个p1
* 5.在p1下添加元素
* 6.在添加完成之后的元素下添加文本 7.回写xml
*/
// 创建解析器
SAXReader saxReader = new SAXReader();
// 得到document
Document document = saxReader.read("src/p1.xml");
// 得到根节点
Element root = document.getRootElement();
// 得到第一个p1元素
Element p1 = root.element("p1");
// 在p1下添加元素
Element sex = p1.addElement("sex");
// 在添加完成之后的元素下添加文本
sex.setText("nv");
// 回写xml
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/p1.xml"), format);
xmlWriter.write(document);
xmlWriter.close();
}
在特定位置添加元素
- 在第一个p1下面的age标签之前添加
<school>ecit</school>
- 创建解析器
- 得到document
- 得到根节点
- 得到第一个p1
- 获取p1下面的所有元素
- elements()方法,返回list集合
- 创建元素,在元素下创建文本:DocumentHelper.createElement(“school”);
- 使用list里的方法,在特定位置添加元素:add(int index, E element)
- 回写xml
// Dom4jUtils类
package cn.itcast.utils;
import java.io.FileOutputStream;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class Dom4jUtils {
public static final String PATH = "src/p1.xml";
// 返回document
public static Document getDocument(String path) {
try {// 创建解析器
SAXReader reader = new SAXReader();
// 得到document
Document document = reader.read(path);
return document;
} catch (DocumentException e) {
e.printStackTrace();
}
return null;
}
// 回写xml
public static void xmlWriters(String path, Document document) {
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter;
try {
xmlWriter = new XMLWriter(new FileOutputStream(path), format);
xmlWriter.write(document);
xmlWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void addSchoolBeforeAge() throws Exception {
/*
* 1.创建解析器
* 2.得到document
* 3.得到根节点
* 4.得到第一个p1
* 5.获取p1下面的所有元素
* elements()方法,返回list集合 创建元素,在元素下创建文本
* DocumentHelper.createElement("school"); 使用list里的方法,在特定位置添加元素 add(int index, E element)
* 6.回写xml
*/
Document document = Dom4jUtils.getDocument("src/p1.xml");
Element root = document.getRootElement();
Element p1 = root.element("p1");
List list = p1.elements();
Element school = DocumentHelper.createElement("school");
school.setText("ecit");
list.add(1, school);
Dom4jUtils.xmlWriters("src/p1.xml", document);
}
使用dom4j实现修改节点的操作
修改第一个p1下面的age元素的值<age>30</age>
// 修改第一个p1下面的age元素的值<age>30</age>
public static void modifyAge() throws Exception {
/*
* 1.创建解析器
* 2.得到document
* 3.得到根节点
* 4.得到第一个p1
* 5.获取p1下面的age元素
* 6.修改age的值
* 7.回写xml
*/
Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
Element root = document.getRootElement();
Element p1 = root.element("p1");
Element age = p1.element("age");
age.setText("30");
Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document);
}
使用dom4j实现删除节点的操作
- 删除第一个p1下面的
<school>ecit</school>
元素
- 创建解析器
- 得到document
- 得到根节点
- 得到第一个p1
- 获取第一个p1下面的school元素
- 回写xml
// 删除第一个p1下面的<school>ecit</school>元素
public static void removeSchool() throws Exception {
/*
* 1.创建解析器
* 2.得到document
* 3.得到根节点
* 4.得到第一个p1
* 5.获取第一个p1下面的school元素
* 6.p1下删除school
* 7.回写xml
*/
Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
Element root = document.getRootElement();
Element p1 = root.element("p1");
Element shcool = p1.element("school");
p1.remove(shcool);
Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document);
}
使用dom4j获取属性的操作
- 获取第一个p1里面的属性id1的值
- 元素.attributeValue(“属性名称”);
// 获取第一个p1里面的属性id1的值
public static void getValues() throws Exception {
/*
* 1.创建解析器
* 2.得到document
* 3.得到根节点
* 4.得到第一个p1
* 5.获取第一个p1的属性值
*/
Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
Element root = document.getRootElement();
Element p1 = root.element("p1");
String s = p1.attributeValue("id1");
System.out.println(s);
}
使用dom4j来支持xpath的操作
可以直接获取到某个元素
- 第一种形式:/AAA/DDD/BBB 表示一层一层的 AAA下的DDD下的BBB
- 第二种形式://BBB 表示只要名称是BBB都可得到
- 第三种形式:/* 表示所有元素
- 第四种形式:BBB[1] 表示第一个BBB元素;BBB[last()] 表示最后一个BBB元素
- 第五种形式://BBB[@id] 表示只要BB元素上有id属性,都得到
- 第六种形式://BBB[@id=’b1’] 表示元素名称是BBB,在BBB上面有id属性,id属性是b1
使用dom4j支持xpath具体操作
- 默认的情况下,dom4j不支持xpath,需要引入支持xpath的jar包 使用
jaxen-1.1-beta-6.jar
- 在dom4j里面提供了两个方法来支持xpath
- selectNodes(“xpath表达式”) 获取多个节点
- selectSingleNode(“xpath表达式”) 获取一个节点
- 使用xpath实现查询xml里面所有的name值
- 所有name元素的xpath表示 //name
// 使用xpath实现查询xml中所有的name值
public static void test1() throws Exception {
/*
* 1.得到document
* 2.直接使用selectNodes("//name")得到所有name元素
*/
Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
List<Node> list = document.selectNodes("//name");
for (Node node : list) {
System.out.println(node.getText());
}
}
- 使用xpath实现获取第一个p1下name的值
- //p1[@id1=’AAA’]/name
// 使用xpath实现获取第一个p1下name的值
public static void test2() throws Exception {
/*
* 1.得到document
* 2.直接使用selectSingleNode("//p1[@id='AAA']/name")
*/
Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
Node node = document.selectSingleNode("//p1[@id1='AAA']/name");
System.out.println(node.getText());
}
实现简单的学生管理系统
使用xml当作数据库,存储学生信息
- 增加操作
- 删除操作
- 查询操作
// student.xml
<?xml version="1.0" encoding="UTF-8"?>
<student>
<stu>
<id>100</id>
<name>zhangsan</name>
<age>20</age>
</stu>
<stu>
<id>101</id>
<name>lisi</name>
<age>30</age>
</stu>
</student>
// Student类
public class Student {
private String id;
private String name;
private String age;
// 省略getter和setter...
}
package cn.itcast.service;
import java.io.FileOutputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import cn.itcast.vo.Student;
public class StuService {
// 增加
public static void addStu(Student stud) throws Exception{
/*
* 1.创建解析器
* 2.得到document
* 3.获取根节点
* 4.在根节点上创建stu标签
* 5.在std标签上依次添加id name age
* 6.在id name age上依次添加值
* 7.回写xml
*/
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("src/student.xml");
Element root = document.getRootElement();
Element stu = root.addElement("stu");
Element id = stu.addElement("id");
Element name = stu.addElement("name");
Element age = stu.addElement("age");
id.setText(stud.getId());
name.setText(stud.getName());
age.setText(stud.getAge());
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/student.xml"), format);
xmlWriter.write(document);
xmlWriter.close();
}
// 删除 根据学生的id删除
public static void delStu(String id) throws Exception{
/*
* 1.创建解析器
* 2.得到document
* 3.获取所有id 使用xpth //id
* 4.遍历list集合
* 5.判断集合id与传递id是否相同
* 6.如果相同,把所在id的stu删除
*/
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("src/student.xml");
List<Node> list = document.selectNodes("//id");
for (Node node : list) {
String idv = node.getText();
if (id.equals(idv)) {
Element stu = node.getParent();
Element stud = stu.getParent();
stud.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 getStu(String id) throws Exception{
/*
* 1.创建解析器
* 2.得到document
* 3.获取所有id 使用xpth //id
* 4.遍历list集合
* 5.判断集合id与传递id是否相同
* 6.如果相同,得到所在的stu
* 7.通过stu得到 name age
*/
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("src/student.xml");
Student student = new Student();
List<Node> list = document.selectNodes("//id");
for (Node node : list) {
String idv = node.getText();
if (id.equals(idv)) {
Element stu = node.getParent();
Element name = stu.element("name");
Element age = stu.element("age");
student.setId(idv);
student.setName(name.getText());
student.setAge(age.getText());
}
}
return student;
}
}