schema的xml约束

一、schema简介
1、dtd语法:<!ELEMENT 元素名称 约束>
2、一个xml中可以有多个schema,多个schema用包名去区分
3、dtd里面有PCDATA类型,但是在schema里面可以支持更多的数据类型
4、schema语法更复杂,目前不能替代dtd
二、schema的快速入门
1、创建一个schema文件 .xsd
** 根节点 <schema>
步骤
- 看xml中有几个元素
<element>
- 看简单元素和复杂元素
* 复杂元素
<complexType>
<sequence>
子元素
</sequence>
</complexType>
* 简单元素
<element name="person">
<complexType>
<sequence>
<element name="name" type="string"></element>
<element name="age" type="int"></element>
</sequence>
</complexType>
</element>
- 在被约束文件里面引入约束文件
xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
表示xml是一个约束文件,xsi是xmlns的一个别称

xmlns="URL地址"
schemaLocation="URL地址 文件名称.xsd"

* sequence表示出现的顺序
* all表示元素只能出现一次
* choice表示元素只能出现其中的一个
* maxOccurs="onbounded" 表示元素出现的次数
* any表示出现任意元素
* 可以约束属性(属性必须是复杂元素)
- 写在</complexType>之前

<attribute name="id1" type="int" use="required"></attribute>
</complexType>
-- name:属性名称
-- type:属性类型
-- use:属性是否必须出现  required
                * 复杂的schema约束案例
		<company xmlns="http://www.example.org/company"
		xmlns:dept = "http://www.example.org/department"
		xmlns:xsi = "http://www.w3c.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://www.example.org/compan company.xsd http://www.example.org/department department.xsd"
		>
			
		<employee age="30">
			<!-- 部门名称 -->
			<dept:name>10</dept:name>
				
			<!-- 员工名称 -->
			<name>王晓晓</name>
		</employee>



三、sax的解析原理
* 解析xml有两种技术 dom和sax

* 根据xml的层级结构在内存分配一个属性结构
* 把xml中的标签,属性,文本封装成对象

* sax方式:时间驱动,边读边解析
* 在javax.xml.parsers包里面
** SAXParser
从 SAXParserFactory.newSAXParser() 获得
- Parse(File f,DefaultHander dh)
** 第一个参数:xml的路径
** 第二个参数:时间处理器
** SAXParserFactory
从 newInstance() 获得

解析过程
* 当解析到开始标签的时候 自动执行startElement方法
* 当解析到文本的时候,自动执行characters方法
* 当解析到结束标签的时候,自动执行endElement方法
四、使用jaxp的sax方式解析xml
* 使用sax方式只能实现查询操作
1、创建解析器工厂
2、创建解析器
3、执行parse方法
4、自己写一个类,继承DefaultHandler抽象类
5、重写方法

// 创建解析器工厂
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
// 创建解析器
SAXParser saxParser = saxParserFactory.newSAXParser();
//
saxParser.parse("NewFile.xml", new defaultHandler());

* 打印整个文档
执行parse方法,第一个参数xml路径,第二个参数是时间处理器
*** 创建一个类,继承处理器的类
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
System.out.println("sName: " + qName);
}


@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
System.out.println(new String(ch, start, length));
}


@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
System.out.println("qName : " + qName);
}

* 获取所有的name元素的值

// 重写DefaultHandler方法
boolean flag = false;


@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
// System.out.println("sName: " + qName);
if ("name".equals(qName)) {
flag = true;
}
}


@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
if (flag == true) {
System.out.println(new String(ch, start, length));
}
}


@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
// System.out.println("qName : " + qName);
if ("name".equals(qName)) {
flag = false;
}
}
* 获取第一个name元素的值

// 重写DefaultHandler方法
boolean flag = false;
int index = 1;


@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
// System.out.println("sName: " + qName);
if ("name".equals(qName) && index == 1) {
flag = true;
}
}


@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
if (flag == true) {
System.out.println(new String(ch, start, length));
}
}


@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
// System.out.println("qName : " + qName);
if ("name".equals(qName)) {
flag = false;
index++;
}
}
五、使用dom4j解析xml

* dom4j不是javase的一部分
—— 导入dom4j的架包
* 得到document
SAXReader reader = new SAXReader();
Document document =  reader.read(url);
* getRootElement();// 获取根节点,返回的是Element
* Element也是一个接口,Node是他的父接口
-- Element和Node里面的方法
** getParent(); 获取父节点
** addElement(); 添加标签

* element(qname); 
-- 获取标签下面额第一个子标签 
-- qname是子标签的名称
* elements(qname);
-- 获取标签下面是这个名称的所有子标签(一层)
-- qname是子标签的名称
* elements();
-- 获取标签下的所有子标签(部分名称)


六、使用dom4j对xml进行操作
1、查询
* 查询所有name元素的值
/*
1、创建解析器工厂
2、得到document
3、得到根节点 getRootElement(); 返回的是Element

4、得到所有的p1
-- elements("p1"); 返回的是list集合
-- 遍历得到每一个p1
5、得到name
-- element("name"); 返回Element
6、得到name里面的值
-- getText();
*/

// 创建工厂
SAXReader saxReader = new SAXReader();
// 得到document
Document document = saxReader.read("NewFile.xml");
// 得到根节点
Element element = document.getRootElement();
// 得到每一个p1
List<Element> list = element.elements("p1");
// 遍历集合
for(Element element1 : list){
// 得到每一个name
Element name1 = element1.element("name");
// 得到每一个值
String s = name1.getText();
System.out.println(s);
}

* 查询第一个name元素的值

/*
1、创建解析器工厂
2、得到document
3、得到根节点 getRootElement(); 返回的是Element

4、得到第一个的p1
-- element("p1"); 返回Element
5、得到name
-- element("name"); 返回Element
6、得到name里面的值
-- getText();
*/

// 创建工厂
SAXReader saxReader = new SAXReader();
// 得到document
Document document = saxReader.read("NewFile.xml");
// 得到根节点
Element root = document.getRootElement();
// 得到第一个p1
Element n = root.element("p1");
// 得到name
Element name = n.element("name");
String s1 = name.getText();
System.out.println(s1);

* 查询第二个name元素的值

/*
1、创建解析器工厂
2、得到document
3、得到根节点 getRootElement(); 返回的是Element

4、得到所有的p1
-- elements("p1"); 返回的是list集合
-- 遍历得到第二个p1 get(index);方法 list.get(1);
5、得到name
-- element("name"); 返回Element
6、得到name里面的值
-- getText();
*/

// 创建工厂
SAXReader saxReader = new SAXReader();
// 得到document
Document document = saxReader.read("NewFile.xml");
// 得到根节点
Element element1  = document.getRootElement();
// 得到所有的p1
List<Element> list = element1.elements("p1");
// 得到最后一个p1元素
Element element2 = list.get(1);
// 得到第二个p1下的name元素
Element name2 = element2.element("name");
// 得到name2下的值
String s2 = name2.getText();
// 输出值
System.out.println(s2);

2、增加操作
* 在第一个p1下面添加<sex>nv</sex>

/*
1、创建解析器工厂
2、得到document
3、得到根节点 getRootElement(); 返回的是Element

4、得到第一个的p1
-- element("p1"); 返回Element
5、在p1下面添加元素 p1.addElement("sex");
p1.addElement("标签名称"); 返回Element
6、添加文本 sex1.setText("nv");
在sex上直接使用 sex1.setText("文本内容");
7、回写xml XMLWriter(outputStream out,outputFormat format)
格式化 OutputFormat,使用createPrettyPrint(); 表示漂亮的格式
使用XMLWriter 不是抽象类 class 可以直接new对象  传递两个参数
-- 第一个参数是路径 new FileOutputStream("路径")
-- 第二个参数是格式化类的值
关闭流
*/

// 创建工厂
SAXReader saxReader = new SAXReader();
// 得到Document
Document document = saxReader.read("NewFile.xml");
// 得到根节点
Element element1 = document.getRootElement();
// 得到p1节点
Element element2 = element1.element("p1");
// 创建节点
Element element3 = element2.addElement("sex");
// 创建文本
element3.addText("nv");
// 回写xml
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter =new XMLWriter(new FileOutputStream("NewFile.xml"),outputFormat);
xmlWriter.write(document);
xmlWriter.close();
3、在特定的位置添加元素
-- 在第一个p1下面的age之前添加<school>gem.sdu.cn</school>

/*
1、创建解析器工厂
2、得到document
3、得到根节点 getRootElement(); 返回的是Element

4、得到第一个的p1
-- element("p1"); 返回Element
5、在p1下面的所有元素 elements(); 返回的是list集合,使用list  在特定的位置添加元素
*** 创建标签和文本 DocumentHelper.createElement("school"); 返回的是Element对象
*** add(int index,E element);element是要添加的元素
6、回写xml XMLWriter(outputStream out,outputFormat format)
格式化 OutputFormat,使用createPrettyPrint(); 表示漂亮的格式
使用XMLWriter 不是抽象类 class 可以直接new对象  传递两个参数
-- 第一个参数是路径 new FileOutputStream("路径")
-- 第二个参数是格式化类的值
关闭流
*/

                // 创建解析器
		SAXReader saxReader = new  SAXReader();
		// 得到document
		Document document = saxReader.read("NewFile.xml");
		// 得到根节点
		Element root = document.getRootElement();
		// 获取第一个p1
		Element e1 = root.element("p1");
		// 获取p1下的多有元素
		List<Element> list = e1.elements();
		// 创建标签和文本
		Element s1 = DocumentHelper.createElement("school");
		s1.setText("geminno.edu.cn");
		// 在特定的位置添加
		list.add(1, s1);
		// 回写xml
		XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("NewFile.xml"), OutputFormat.createPrettyPrint());
		xmlWriter.write(document);
		xmlWriter.close();	


4、修改操作
修改第一个p1下的age属性的值 <age>30</age>

/*
1、创建解析器工厂
2、得到document
3、得到根节点 getRootElement(); 返回的是Element

4、得到第一个的p1
-- element("p1"); 返回Element
5、在p1下面的age,修改值为30

6、回写xml XMLWriter(outputStream out,outputFormat format)
格式化 OutputFormat,使用createPrettyPrint(); 表示漂亮的格式
使用XMLWriter 不是抽象类 class 可以直接new对象  传递两个参数
-- 第一个参数是路径 new FileOutputStream("路径")
-- 第二个参数是格式化类的值
关闭流
*/
5、 删除操作
删除第一个p1下的school属性的值 <school>gem.sdu.cn</school>

/*
1、创建解析器工厂
2、得到document
3、得到根节点 getRootElement(); 返回的是Element

4、得到第一个的p1
-- element("p1"); 返回Element
5、在p1下面的school,使用p1删除school
-- 通过父节点进行删除
** 第一种直接删除
** 第二种得到父节点 getParent();进行删除
6、回写xml XMLWriter(outputStream out,outputFormat format)
格式化 OutputFormat,使用createPrettyPrint(); 表示漂亮的格式
使用XMLWriter 不是抽象类 class 可以直接new对象  传递两个参数
-- 第一个参数是路径 new FileOutputStream("路径")
-- 第二个参数是格式化类的值
关闭流
*/

七、使用dom4j对属性进行操作
* 获取第一个p1里面的属性id1值
/*
1、创建解析器工厂
2、得到document
3、得到根节点 getRootElement(); 返回的是Element

4、得到第一个的p1
-- element("p1"); 返回Element
5、得到p1里面的属性值
p1.attributeValue("id1");
*/

// 创建解析器
SAXReader saxReader = new  SAXReader();
// 得到document
Document document = saxReader.read("NewFile.xml");
// 得到根节点
Element root = document.getRootElement();
// 获取第一个p1
Element e1 = root.element("p1");
// 获取p1里面的属性值
String value = p1.attributeValue("id1");
System.out.println(value);

八、使用dom4j支持xpath的操作
* 可以直接获取某个元素
* 第一种形式
/AAA/BBB/CCC:表示获取AAA下的CCC
* 第二种形式
//BBB : 表示只要名称是BBB,都可以得到
* 第三种形式
/*: 获取所有的元素
* 第四种形式
/AAA/BBB[1]:表示获取aaa下的第一个bbb元素
/AAA/BBB[last()]:表示获取aaa下的最后一个bbb元素
* 第五种形式
//BBB[@id]:表示只要bbb上有id这个属性,都可以获取到
* 第六种形式
//BBB[@id='b1']:表示只要bbb上有id这个属性并且这个id属性的值是b1,都可以获取
九、使用dom4j支持xpath的具体的操作
* 默认情况下dom4j不支持xpath
需要引入支持xpath的架包 jaxen-1.1-beta-6.jar
* 在dom4j中提供了两个方法来支持xpath
-- selectNodes("xpath表达式");
- 获取多个节点
-- selectSingleNode("xpath表达式");
- 获取单个节点
* 使用xpath实现:查询所有的name元素的值
** //name
/*
1、得到document
2、直接使用selectNodes("//name");得到所有的name元素

*/
* 使用xpath实现:查询第一个p1下的name值
** //p1[@id='aaa']/name

/*
1、得到document
2、直接使用selectSingleNode("//p1[@id='aaa']/name");得到name元素

*/

十、实现简单的学生信息管理系统
** 使用xml文件存贮学生信息

// 添加方法
public static void add(Student student) throws Exception{
// 创建解析器
SAXReader saxReader = new SAXReader();
// 得到document
Document document =  saxReader.read("student.xml");
// 得到根节点
Element root = document.getRootElement();
// 创建stu节点
Element stu1 = root.addElement("stu");
// 在stu1下依次创建 id name age 节点
Element id1 = stu1.addElement("id");
Element name1 = stu1.addElement("name");
Element age1 = stu1.addElement("age");
// 在stu1下依次创建 id name age 节点并设置值
id1.setText(student.getId());
name1.setText(student.getName());
age1.setText(student.getAge());
// 回写xml
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("student.xml"),OutputFormat.createPrettyPrint());
xmlWriter.write(document);
xmlWriter.close();
}

// 删除方法
public static void del(String id) throws Exception{
// 创建解析器
SAXReader saxReader = new SAXReader();
// 获取解析器
Document document = saxReader.read("student.xml");
// 获取所有的id
List<Node> list = document.selectNodes("//id");
// 遍历集合
for (Node node : list) {
// 得到所在的值
String s1 = node.getText();
// 判断id是否相等
if(s1.equals(id)){// 若相等
// 获取stu
Element stu1 = node.getParent();
// 获取student
Element student1 = stu1.getParent();
// 通过父节点进行删除
student1.remove(stu1);
}
}

                        // 回写xml
			XMLWriterxmlWriter=newXMLWriter(new FileOutputStream("student.xml"),OutputFormat.createPrettyPrint());
			xmlWriter.write(document);
			xmlWriter.close();


}

// 查询方法
public static Student getStu(String id) throws Exception{
// 创建解析器
SAXReader saxReader = new SAXReader();
// 得到document
Document document = saxReader.read("student.xml");
// 得到所有的id
List<Node> list = document.selectNodes("//id");
// 得到student对象
Student stu1 = new Student();
// 遍历集合
for (Node node : list) {
// 得到具体的值
String s2 = node.getText();
// 判断id是否相等
if(s2.equals(id)){
// 得到其父节点stu
Element stu = node.getParent();
// 通过stu来获取id和name值
String name1 = stu.element("name").getText();
String age1 = stu.element("age").getText();
stu1.setId(s2);
stu1.setName(name1);
stu1.setAge(age1);
}
}

return stu1;
}

猜你喜欢

转载自blog.csdn.net/qq_34668848/article/details/80971809