XML编程
主要内容
l XML及其语法
l XML约束之DTD
l XML编程(CRUD---CreateRead Update Delete)
l XML约束之Schema
XML及其语法
什么是XML
l XML是指可扩展标记语言(eXtensibleMarkup Language),它是一种标记语言,很类似HTML。它被设计的宗旨是传输数据,而非显示数据。
l XML标签没有被预定义,需要用户自行定义标签。
l XML技术是W3C组织(WorldWide Web Consortium万维网联盟)发布的,目前遵循的是W3C组织于2000年发布的XML1.0规范。
l XML被广泛认为是继Java之后在Internet上最激动人心的新技术。
XML技术用于解决什么问题?
l 在现实生活中存在大量有关系的数据,如右图所示。
l 问题:这样的数据该如何表示并交给计算机处理呢?
XML技术用于解决什么问题?
l XML语言出现的根本目的在于描述向上图那种有关系的数据。
l XML是一种通用的数据交换格式。
l 在XML语言中,它允许用户自定义标签。一个标签用于描述一段数据;一个标签可分为开始标签和结束标签,在起始标签之间,又可以使用其它标签描述其它数据,以此来实现数据关系的描述。
l XML中的数据必须通过软件程序来解析执行或显示,如IE;这样的解析程序称之为Parser(解析器)。
<?xmlversion="1.0" encoding="UTF-8"?>
<中国>
<北京>
<海淀></海淀>
<丰台></丰台>
</北京>
<山东>
<济南></济南>
<青岛></青岛>
</山东>
<湖北>
<武汉></武汉>
<荆州></荆州>
</湖北>
</中国>
XML常见应用
l 在Java开发中,传统的配置文件是*.properties属性文件(key=value),而XML表示的数据更为丰富。
l XML技术除用于描述有关系的数据外,还经常用作软件配置文件,以描述程序模块之间的关系。(如后面将要学习到的Struts、Spring和Hibernate都是基于XML作为配置文件的)
l 在一个软件系统中,通过XML配置文件可以提高系统的灵活性。即程序的行为是通过XML文件来配置的,而不是硬编码。
XML文档的组成
l 一个XML文件一般由以下几部分组成:
• 文档声明
• 元素
• 元素的属性
• 注释
• CDATA区
• 特殊字符
• 处理指令(PI:ProcessingInstruction)
文档声明
l 在编写XML文档时,需要先使用文档声明来声明XML文档。且必须出现在文档的第一行。
l 最简单的语法:<?xml version=“1.0”?>
l 用encoding属性说明文档所使用的字符编码,默认为UTF-8。保存在磁盘上的文件编码要与声明的编码一致。
如:<?xmlversion=“1.0”encoding=“GB2312”?>
l 用standalone属性说明文档是否独立,即是否依赖其他文档。
如:<?xmlversion=“1.0”standalone=“yes”?>
元素(1)
l XML元素指XML文件中出现的标签。一个标签分为起始和结束标签(不能省略)。一个标签有如下几种书写形式:
• 包含标签主体:<mytag>somecontent</mytag>
• 不含标签主体:<mytag/> == <mytag></mytag> <br/><hr/>
l 一个标签中可以嵌套若干子标签,但所有标签必须合理的嵌套,不允许有交叉嵌套。
• <mytag1><mytag2></mytag1></mytag2> WRONG
l 一个XML文档必须有且仅有一个根标签,其他标签都是这个根标签的子标签或孙标签。
元素(2)
l XML中不会忽略主体内容中出现的空格和换行。
元素(3)--元素命名规范
l 元素(标签)的名称可以包含字母、数字、减号、下划线和英文句点,但必须遵守下面的一些规范:
• 严格区分大小写;<P> <p>
• 只能以字母或下划线开头;abc _abc
• 不能以xml(或XML、Xml等)开头----W3C保留日后使用;
• 名称字符之间不能有空格或制表符;ab
• 名称字符之间不能使用冒号;(有特殊用途)
元素的属性
l 一个元素可以有多个属性,每个属性都有它自己的名称和取值,例如:<mytagname=“value”…/>
l 属性值一定要用引号(单引号或双引号)引起来。
l 属性名称的命名规范与元素的命名规范相同
l 元素中的属性是不允许重复的
l 在XML技术中,标签属性所代表的信息也可以被改成用子元素的形式来描述,例如:
注释
l XML中的注释语法为:<!--这是注释-->
l 注意:
• XML声明之前不能有注释
• 注释不能嵌套,例如:

CDATA区
l CDATA是CharacterData的缩写
l 作用:把标签当做普通文本内容;
l 语法:<![CDATA[内容]]>
特殊字符
l 对于一些特殊字符,若要在元素主体内容中显示,必须进行转义。

处理指令
l 处理指令,简称PI(ProcessingInstruction)。
l 作用:用来指挥软件如何解析XML文档。
l 语法:必须以“<?”作为开头,以“?>”作为结尾。
l 常用处理指令:
• XML声明:<?xmlversion=“1.0”encoding=“GB2312”?>
• xml-stylesheet指令:
• 作用:指示XML文档所使用的CSS样式XSL。
XML约束之DTD
为什么需要约束
l XML都是用户自定义的标签,若出现小小的错误,软件程序将不能正确地获取文件中的内容而报错。(如:Tomcat)
l XML技术中,可以编写一个文档来约束一个XML的书写规范,这个文档称之为约束。
l 两个概念:
• 格式良好的XML:遵循XML语法的XML(不一定是有效的)
• 有效的XML:遵循约束文档的XML(有效的一定就是格式良好的)
l 总之:约束文档定义了在XML中允许出现的元素名称、属性及元素出现的顺序等等。
常用的约束技术
l XML DTD
l XDR
l SOX
l XML Schema
DTD快速入门
l DTD(Document TypeDefinition):文档类型定义。
l 作用:约束XML的书写规范
验证XML的有效性
l 如何根据DTD中定义的内容来验证XML书写是否正确呢?
l 答:需要软件程序,即解析器
l 根据能否对XML文档进行约束模式校验,可以将解析器分为两类:
• 非校验解析器,如IE
• 校验解析器
编程校验XML文档的正确性

编写DTD的方式
l DTD约束文档可以在XML文档中直接定义,也可以作为单独的文档进行编写(单独的文档必须以UTF-8编码进行保存)。
l 在XML文档中编写DTD示例
引入外部DTD文档
l XML使用DOCTYPE声明语句来指明它所遵循的DTD文档,有两种形式:
• 当引用的DTD文档在本地时,采用如下方式:
<!DOCTYPE根元素SYSTEM“DTD文档路径”>
如:<!DOCTYPE书架SYSTEM “book.dtd”>
• 当引用的DTD文档在公共网络上时,采用如下方式:
<!DOCTYPE根元素PUBLIC“DTD名称”“DTD文档的URL”>
如:<!DOCTYPEweb-app PUBLIC
"-//Sun Microsystems, Inc.//DTD WebApplication 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
DTD语法细节
l DTD文档的语法主要涉及以下内容的定义:
• 定义元素
• 定义属性
• 定义实体
DTD-定义元素
l 在DTD文档中使用ELEMENT关键字来声明一个XML元素。
l 语法:<!ELEMENT 元素名称使用规则>
• 使用规则:
• (#PCDATA):指示元素的主体内容只能是普通的文本.(ParsedCharacter Data)
• EMPTY:用于指示元素的主体为空。比如<br/>
• ANY:用于指示元素的主体内容为任意类型。
• (子元素):指示元素中包含的子元素
• 定义子元素及描述它们的关系:
• 如果子元素用逗号分开,说明必须按照声明顺序去编写XML文档。
如: <!ELEMENT FILE (TITLE,AUTHOR,EMAIL)
• 如果子元素用“|”分开,说明任选其一。
如:<!ELEMENT FILE (TITLE|AUTHOR|EMAIL)
• 用+、*、?来表示元素出现的次数
• 如果元素后面没有+*?:表示必须且只能出现一次
• +:表示至少出现一次,一次或多次
• *:表示可有可无,零次、一次或多次
• ?:表示可以有也可以无,有的话只能有一次。零次或一次
• 如:<!ELEMENT MYFILE ((TITLE*, AUTHOR?,EMAIL)* | COMMENT)>
DTD--定义属性1
l 在DTD文档中使用ATTLIST关键字来为一个元素声明属性。
l 语法:


DTD--定义属性2
l 属性值类型:
• CDATA:表示属性的取值为普通的文本字符串
• ENUMERATED (DTD没有此关键字):表示枚举,只能从枚举列表中任选其一,如(鸡肉|牛肉|猪肉|鱼肉)
• ID:表示属性的取值不能重复
l 设置说明
• #REQUIRED:表示该属性必须出现
• #IMPLIED:表示该属性可有可无
• #FIXED:表示属性的取值为一个固定值。语法:#FIXED"固定值"
• 直接值:表示属性的取值为该默认值
DTD--定义属性示例

DTD--定义属性示例
l ID表示属性的设置值为一个唯一值。
<?xml version ="1.0" encoding="GB2312" ?>
<!DOCTYPE 联系人列表[
<!ELEMENT 联系人列表 ANY>
<!ELEMENT 联系人(姓名,EMAIL)>
<!ELEMENT 姓名(#PCDATA)>
<!ELEMENT EMAIL(#PCDATA)>
<!ATTLIST 联系人 编号 ID #REQUIRED>
]>
<联系人列表>
<联系人 编号=“a">
<姓名>张三</姓名>
<EMAIL>zhang@it315.org</EMAIL>
</联系人>
<联系人 编号=“b">
<姓名>李四</姓名>
<EMAIL>li@it315.org</EMAIL>
</联系人>
</联系人列表>
DTD--定义实体
l 定义实体就是为一段内容指定一个名称,使用时通过这个名称就可以引用其所代表的内容。
l 在DTD文档中使用ENTITY关键字来声明一个实体。
l 实体可分为:引用实体和参数实体,两者的语法不同
定义引用实体
l 概念:在DTD中定义,在XML中使用
l 语法:<!ENTITY 实体名称“实体内容”>
l 引用方式(注意是在XML中使用):&实体名称;
定义参数实体(了解)
l 概念:在DTD中定义,在DTD中使用
l 语法:<!ENTITY % 实体名称“实体内容”>
l 引用方式(注意是在DTD中使用):%实体名称;
XML及DTD练习
l XML练习题
l DTD实例

XML编程(用Java编写解析器)
Java解析XML概述
l XML解析方式分为两种:DOM方式和SAX方式
• DOM:DocumentObject Model,文档对象模型。这种方式是W3C推荐的处理XML的一种方式。
• SAX:SimpleAPI for XML。这种方式不是官方标准,属于开源社区XML-DEV,几乎所有的XML解析器都支持它。
l XML解析开发包
• JAXP:是SUN公司推出的解析标准实现。JDK
• Dom4J:是开源组织推出的解析开发包。(牛,大家都在用,包括SUN公司的一些技术的实现都在用)
• JDom:是开源组织推出的解析开发包。
JAXP
l JAXP:(Java API for XMLProcessing)开发包是JavaSE的一部分,它由以下几个包及其子包组成:
• org.w3c.dom:提供DOM方式解析XML的标准接口
• org.xml.sax:提供SAX方式解析XML的标准接口
• javax.xml:提供了解析XML文档的类
l javax.xml.parsers包中,定义了几个工厂类。我们可以通过调用这些工厂类,得到对XML文档进行解析的DOM和SAX解析器对象。
• DocumentBuilderFactory
• SAXParserFactory
使用JAXP进行DOM解析
l javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象,DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。

获得JAXP中的DOM解析器
l 调用DocumentBuilderFactory.newInstance() 方法得到创建DOM 解析器的工厂。
l 调用工厂对象的newDocumentBuilder方法得到DOM 解析器对象。
l 调用DOM 解析器对象的parse()方法解析XML 文档,得到代表整个文档的Document对象,进行可以利用DOM特性对整个XML文档进行操作了。
Tip:DOM编程
l DOM模型(document object model)
• DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
• 在dom中,节点之间关系如下:
• 位于一个节点之上的节点是该节点的父节点(parent)
• 一个节点之下的节点是该节点的子节点(children)
• 同一层次,具有相同父节点的节点是兄弟节点(sibling)
• 一个节点的下一个层次的节点集合是节点后代(descendant)
• 父、祖父节点及所有位于节点上面的,都是节点的祖先(ancestor)
• 节点类型(下页ppt)
Node对象
l Node对象提供了一系列常量来代表结点的类型,当开发人员获得某个Node类型后,就可以把Node节点转换成相应的节点对象(Node的子类对象),以便于调用其特有的方法。(查看API文档)
l Node对象提供了相应的方法去获得它的父结点或子结点。编程人员通过这些方法就可以读取整个XML文档的内容、或添加、修改、删除XML文档的内容了。
DOM方式解析XML文件
l DOM解析编程
• 1、得到某个具体的节点内容
• 2、遍历所有元素节点
• 3、修改某个元素节点的主体内容
• 4、向指定元素节点中增加子元素节点
• 5、向指定元素节点上增加同级元素节点
• 6、删除指定元素节点
• 7、操作XML文件属性
<?xml version="1.0" encoding="UTF-8" standalone="no"?><exam>
<student examid="323" idcard="111">
<name>Jim</name>
<location>沈阳</location>
<grade>89</grade>
<age>23</age></student>
<student examid="444" idcard="333">
<age>24</age>
<name>Tom</name>
<location>大连</location>
<grade>97</grade>
</student>
</exam>
package cn.simplefile.xml;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* 实现Jaxp 的增删检查操作
*/
public class JaxpCURD {
public static void main(String[] args) throws Exception {
// get DocumentBuilder
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
//get xml file Document
Document document = db.parse("src/student.xml");
// test1(document);
// test2(document);
// test3(document);
// test4(document);
// test5(document);
// test6(document);
// test7(document);
test8(document);
}
//获取某个节点的内容
private static void test1(Document document){
NodeList list = document.getElementsByTagName("name");
// System.out.println(list.getLength());
Node node = list.item(1);
System.out.println(node.getTextContent());
}
// 遍历所有元素的节点:递归
private static void test2(Node node){
// 判断node是否是元素节点
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println(node.getNodeName());
}
// 判断它是否有孩子节点,循环遍历
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node n = children.item(i);
// 递归调用
test2(n);
}
}
// 修改某个节点的主体内容
private static void test3(Document document) throws Exception{
// 得到某个第一个节点的内容容
Node node = document.getElementsByTagName("name").item(0);
// 修改主体内容
node.setTextContent("Jim");
// 更新XML文档
// 利用Transformer的transform更新文档
// 得到Transformer对象
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult("src/student.xml"));
}
// 向指定元素节点中增加子元素节点
private static void test4(Document document) throws Exception{
// 得到节点
Node node = document.getElementsByTagName("student").item(0);
// 创建新节点,并设置主体内容
Element newEle = document.createElement("age");
newEle.setTextContent("23");
// 建立和原节点的关系
node.appendChild(newEle);
// 更新xml文档
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult("src/student.xml"));
}
// 向指定元素节点上增加同级元素节点
private static void test5(Document document) throws Exception{
// 找到需要的节点
Node node = document.getElementsByTagName("name").item(1);
// 创建新的节点
Element e = document.createElement("age");
e.setTextContent("24");
// 由父节点完成插入操作
node.getParentNode().insertBefore(e, node);
// 更新xml文档
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult("src/student.xml"));
}
// 删除指定元素节点
private static void test6(Document document) throws Exception{
// 得到内部节点
Node node = document.getElementsByTagName("name").item(1);
// 用其父节点删除
node.getParentNode().removeChild(node);
// 更新xml文档
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult("src/student.xml"));
}
// 操作节点的属性
// 得到节点的属性
private static void test7(Document document){
// 得到节点元素
Node node = document.getElementsByTagName("student").item(0);
// 设置节点属性
// 如果节点是元素节点 则可以设置属性
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element)node;
System.out.println(e.getAttribute("examid"));
}
}
// 设置节点的属性
private static void test8(Document document) throws Exception{
// 得到节点元素
Node node = document.getElementsByTagName("student").item(0);
// 设置属性
Element e = (Element) node;
e.setAttribute("examid", "323");
// 更新xml文档
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult("src/student.xml"));
}
}
l DOM编程练习
1、以如下格式的exam.xml文件为例
<?xml version="1.0" encoding="UTF-8"standalone="no"?>
<exam>
<student idcard="111" examid="222">
<name>张三</name>
<location>沈阳</location>
<grade>89</grade>
</student>
<student idcard="333" examid="444">
<name>李四</name>
<location>大连</location>
<grade>97</grade>
</student>
</exam>
2、编程实现如下功能
3、实现学生信息的添加
4、实现学生信息的查询
5、实现学生的删除功能

先建立XML文档,然后再在不同的包下写代码
cn.example.util包
package cn.example.utils;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
/**
* 工具类
* 功能: 获取Document对象,更新xml文档
*/
public class XmlUtil {
// 获取Document对象
public static Document getDocument() throws Exception{
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = db.parse("src/student.xml");
return document;
}
// 更新xml文档
public static void write2Xml(Document document) throws Exception{
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.transform(new DOMSource(document), new StreamResult("src/student.xml"));
}
}
cn.example.domain包
package cn.example.domain;
// 代表学生信息的JavaBeann
public class Student {
private String name;
private String location;
private float grade;
private String examid;// 准考证号
private String idcard;// 身份证号
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public float getGrade() {
return grade;
}
public void setGrade(float grade) {
this.grade = grade;
}
public String getExamid() {
return examid;
}
public void setExamid(String examid) {
this.examid = examid;
}
public String getIdcard() {
return idcard;
}
public void setIdcard(String idcard) {
this.idcard = idcard;
}
@Override
public String toString() {
return "姓名=" + name + ", 地址=" + location + ", 成绩="
+ grade + ", 准考证号=" + examid + ", 身份证号=" + idcard;
}
}
cn.example.dao包
package cn.example.dao;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import cn.example.domain.Student;
import cn.example.utils.XmlUtil;
/**
* 完成学生类的增删改查
*/
public class StudentDao {
boolean result = false;
// 添加学生
public boolean addStudent(Student student) {
try {
// 得到Document对象
Document document = XmlUtil.getDocument();
// 创建新元素节点和属性
Element stu = document.createElement("student");
stu.setAttribute("examid", student.getExamid());
stu.setAttribute("idcard", student.getIdcard());
// 创建子元素节点
Element name = document.createElement("name");
name.setTextContent(student.getName());
Element location = document.createElement("location");
location.setTextContent(student.getLocation());
Element grade = document.createElement("grade");
grade.setTextContent(student.getGrade() + "");
// 确定他们之间的关系
stu.appendChild(name);
stu.appendChild(location);
stu.appendChild(grade);
document.getElementsByTagName("exam").item(0).appendChild(stu);
// 更新XML文档
XmlUtil.write2Xml(document);
result = true;
} catch (Exception e) {
// 异常转义,由编译异常转为运行异常
throw new RuntimeException(e);
}
return result;
}
// 删除学生
public boolean removeStudent(String name) {
boolean result = false;
try {
// 得到DOM对象
Document document = XmlUtil.getDocument();
// 得到要删除的节点
NodeList list = document.getElementsByTagName("name");
// 循环遍历所有节点
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
// 利用根节点删除父节点
if (node.getTextContent().equals(name.trim())) {
node.getParentNode().getParentNode().removeChild(node.getParentNode());
// 更新XML文档
XmlUtil.write2Xml(document);
result = true;
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return result;
}
// 查询学生信息
public Student queryStudent(String examid) {
Student student = null;
try {
// 创建dom对象
Document document = XmlUtil.getDocument();
// 得到所有的student元素
NodeList list = document.getElementsByTagName("student");
// 循环遍历匹配与examid相等的节点
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
Element e = (Element) node;
if (e.getAttribute("examid").equals(examid.trim())) {
// 获取该节点的信息
student = new Student();
student.setExamid(examid);
student.setIdcard(e.getAttribute("idcard"));
student.setName(e.getElementsByTagName("name").item(0).getTextContent());
student.setLocation(e.getElementsByTagName("location").item(0).getTextContent());
student.setGrade(Float.parseFloat(e.getElementsByTagName("grade").item(0).getTextContent()));
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return student;
}
}
cn.example.test包
package cn.example.test;
import cn.example.dao.StudentDao;
import cn.example.domain.Student;
public class StudentDaoTest {
public static void main(String[] args) {
Student student = new Student();
student.setName("Tam");
student.setExamid("12312");
student.setGrade(100f);
student.setIdcard("123121");
student.setLocation("Hongkong");
StudentDao dao = new StudentDao();
dao.addStudent(student);
// dao.removeStudent("Tam");
Student s = dao.queryStudent("12312");
System.out.println(s);
}
}
cn.example.ui包
package cn.example.ui;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import cn.example.dao.StudentDao;
import cn.example.domain.Student;
/**
* 用户操作界面
*/
public class Main {
public static void main(String[] args) {
StudentDao dao = new StudentDao();
// 打印操作提示
System.out.println("添加用户:(a)\t删除用户:(b)\t查询成绩:(c)");
System.out.println("请输入操作类型:");
// 接收用户的操作
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
String operation = br.readLine();
if ("a".equals(operation)) {
// 添加操作
System.out.println("请输入学生姓名:");
String name = br.readLine();
System.out.println("请输入学生准考证号:");
String examid = br.readLine();
System.out.println("请输入学生身份证号:");
String idcard = br.readLine();
System.out.println("请输入学生所在地:");
String location = br.readLine();
System.out.println("请输入学生成绩:");
String grade = br.readLine();
Student student = new Student();
student.setExamid(examid);
student.setIdcard(idcard);
student.setName(name);
student.setGrade(Float.parseFloat(grade));
student.setLocation(location);
boolean result = dao.addStudent(student);
if (result) {
System.out.println("----添加数据成功-----");
} else {
System.out.println("----添加数据失败-----");
}
} else if ("b".equals(operation)) {
// 删除操作
System.out.println("请输入删除的学生的姓名:");
String name = br.readLine();
boolean result = dao.removeStudent(name);
if (result) {
System.out.println("----已成功删除学生信息-----");
} else {
System.out.println("----删除学生信息失败-----");
}
} else if ("c".equals(operation)) {
// 查询操作
System.out.println("请输入查询的学生的准考证号");
String examid = br.readLine();
Student student = dao.queryStudent(examid);
if (student == null) {
System.out.println("学生不存在");
}else{
System.out.println(student);
}
} else {
System.out.println("输入错误");
}
} catch (Exception e) {
System.out.println("输入错误");
}
}
}
更新XML文档
l javax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换为某种格式后进行输出,例如把xml文件应用样式表后转成一个html文档。利用这个对象,当然也可以把Document对象又重新写入到一个XML文件中。
l Transformer类通过transform方法完成转换操作,该方法接收一个源和一个目的地。我们可以通过:
• javax.xml.transform.dom.DOMSource类来关联要转换的document对象,
• 用javax.xml.transform.stream.StreamResult对象来表示数据的目的地。
l Transformer对象通过TransformerFactory获得。
SAX解析
l 在使用DOM 解析XML文档时,需要读取整个XML 文档,在内存中构架代表整个DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。
l SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。
SAX解析
l SAX采用事件处理的方式解析XML文件,利用SAX 解析XML文档,涉及两个部分:解析器和事件处理器:
• 解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。
• 解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
• 事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
SAX解析


SAX方式解析XML文档
l 使用SAXParserFactory创建SAX解析工厂
SAXParserFactoryspf = SAXParserFactory.newInstance();
l 通过SAX解析工厂得到解析器对象
SAXParsersp = spf.newSAXParser();
l 通过解析器对象得到一个XML的读取器
XMLReaderxmlReader = sp.getXMLReader();
l 设置读取器的事件处理器
xmlReader.setContentHandler(newBookParserHandler());
l 解析xml文件
xmlReader.parse("book.xml");
SAX方式解析XML文档
l SAX解析编程
DOM4J解析XML文档
l Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。
l Dom4j是一个非常优秀的JavaXML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。
l 使用Dom4j开发,需下载dom4j相应的jar文件。
Document对象
l DOM4j中,获得Document对象的方式有三种:
1.读取XML文件,获得document对象
SAXReaderreader = new SAXReader();
Document document =reader.read(new File("input.xml"));
2.解析XML形式的文本,得到document对象.
String text = "<members></members>";
Document document = DocumentHelper.parseText(text);
3.主动创建document对象.
Document document = DocumentHelper.createDocument();
//创建根节点
Element root =document.addElement("members");
节点对象
l 1.获取文档的根节点.
Element root = document.getRootElement();
l 2.取得某个节点的子节点.
Element element=node.element(“书名");
l 3.取得节点的文字
Stringtext=node.getText();
l 4.取得某节点下所有名为“member”的子节点,并进行遍历.
List nodes =rootElm.elements("member");
for (Iterator it = nodes.iterator();it.hasNext();) {
Element elm = (Element) it.next();
//do something
}
l 5.对某节点下的所有子节点进行遍历.
for(Iteratorit=root.elementIterator();it.hasNext();){
Elementelement = (Element) it.next();
//do something
}
l 6.在某节点下添加子节点.
Element ageElm = newMemberElm.addElement("age");
l 7.设置节点文字.
element.setText("29");
l 8.删除某节点.
//childElm是待删除的节点,parentElm是其父节点
parentElm.remove(childElm);
l 9.添加一个CDATA节点.
Element contentElm = infoElm.addElement("content");
contentElm.addCDATA(diary.getContent());
节点对象属性
l 1.取得某节点下的某属性
Elementroot=document.getRootElement();
//属性名name
Attributeattribute=root.attribute("size");
l 2.取得属性的文字
Stringtext=attribute.getText();
l 3.删除某属性
Attributeattribute=root.attribute("size");
root.remove(attribute);
节点对象属性
l 3.遍历某节点的所有属性
Elementroot=document.getRootElement();
for(Iteratorit=root.attributeIterator();it.hasNext();){
Attributeattribute = (Attribute) it.next();
Stringtext=attribute.getText();
System.out.println(text);
}
l 4.设置某节点的属性和文字.
newMemberElm.addAttribute("name", "sitinspring");
l 5.设置属性的文字
Attributeattribute=root.attribute("name");
attribute.setText("sitinspring");
将文档写入XML文件.
l 1.文档中全为英文,不设置编码,直接写入的形式.
XMLWriter writer = newXMLWriter(new FileWriter("output.xml"));
writer.write(document);
writer.close();
l 2.文档中含有中文,设置编码格式写入的形式.
OutputFormat format = OutputFormat.createPrettyPrint();
// 指定XML编码
format.setEncoding("GBK");
XMLWriter writer = new XMLWriter(new FileOutputStream ("output.xml"),format);
writer.write(document);
writer.close();
Dom4j在指定位置插入节点
l 1.得到插入位置的节点列表(list)
l 2.调用list.add(index,elemnent),由index决定element的插入位置。
l Element元素可以通过DocumentHelper对象得到。示例代码:
Elementaaa = DocumentHelper.createElement("aaa");
aaa.setText("aaa");
Listlist = root.element("书").elements();
list.add(1,aaa);
//更新document
字符串与XML的转换
l 1.将字符串转化为XML
String text = "<members><member>sitinspring</member></members>";
Document document = DocumentHelper.parseText(text);
l 2.将文档或节点的XML转化为字符串.
SAXReader reader = new SAXReader();
Document document =reader.read(new File("input.xml"));
Element root=document.getRootElement();
String docXmlText=document.asXML();
StringrootXmlText=root.asXML();
Element memberElm=root.element("member");
String memberXmlText=memberElm.asXML();
XML约束之Schema
XML Schema
l XML Schema 也是一种用于定义和描述XML 文档结构与内容的模式语言,其出现是为了克服DTD 的局限性
l XML Schema VS DTD:
• XML Schema符合XML语法结构。
• DOM、SAX等XMLAPI很容易解析出XML Schema文档中的内容。
• XML Schema对名称空间支持得非常好。
• XML Schema比XMLDTD支持更多的数据类型,并支持用户自定义新的数据类型。
• XML Schema定义约束的能力非常强大,可以对XML实例文档作出细致的语义限制。
• XML Schema不能像DTD一样定义实体,比DTD更复杂,但XmlSchema现在已是w3c组织的标准,它正逐步取代DTD。
Schema约束快速入门

Schema入门案例
<?xmlversion="1.0" encoding="UTF-8" ?>
<xs:schemaxmlns:xs=“http://www.w3.org/2001/XMLSchema”//标准的名称空间
targetNamespace=“http://www.itcast.cn” //将该schema文档绑定到http://www.itcast.cn名称空间
elementFormDefault="qualified">
<xs:element name='书架' >
<xs:complexType>
<xs:sequence maxOccurs='unbounded' >
<xs:element name='书' >
<xs:complexType>
<xs:sequence>
<xs:elementname='书名' type='xs:string' />
<xs:element name='作者' type='xs:string' />
<xs:element name='售价' type='xs:string' />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Schema入门案例
<?xmlversion="1.0" encoding="UTF-8"?>
<itcast:书架 xmlns:itcast="http://www.itcast.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=“http://www.itcast.cnbook.xsd">
<itcast:书>
<itcast:书名>JavaScript网页开发</itcast:书名>
<itcast:作者>张孝祥</itcast:作者>
<itcast:售价>28.00元</itcast:售价>
</itcast:书>
</itcast:书架>
名称空间的概念
l 在XML Schema中,每个约束模式文档都可以被赋以一个唯一的名称空间,名称空间用一个唯一的URI(UniformResource Identifier,统一资源标识符)表示。在Xml文件中书写标签时,可以通过名称空间声明(xmlns),来声明当前编写的标签来自哪个Schema约束文档。如:
<itcast:书架 xmlns:itcast=“http://www.itcast.cn”>
<itcast:书>……</itcast:书>
</itcast:书架>
此处使用itcast来指向声明的名称,以便于后面对名称空间的引用。
l 注意:名称空间的名字语法容易让人混淆,尽管以http://开始,那个URL 并不指向一个包含模式定义的文件。事实上,这个URL:http://www.itcast.cn根本没有指向任何文件,只是一个分配的名字。
使用名称空间引入Schema
l 为了在一个XML文档中声明它所遵循的Schema文件的具体位置,通常需要在Xml文档中的根结点中使用schemaLocation属性来指定,例如:
<itcast:书架 xmlns:itcast="http://www.itcast.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=“http://www.itcast.cnbook.xsd">
l schemaLocation此属性有两个值。第一个值是需要使用的命名空间。第二个值是供命名空间使用的XML schema 的位置,两者之间用空格分隔。
l 注意,在使用schemaLocation属性时,也需要指定该属性来自哪里。
使用默认名称空间
l 基本格式:
xmlns="URI"
l 举例:
<书架 xmlns="http://www.it315.org/xmlbook/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=“http://www.itcast.cnbook.xsd">
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00元</售价>
</书>
<书架>
使用名称空间引入多个XML Schema文档

不使用名称空间引入XML Schema文档

在XML Schema文档中声明名称空间

Schema语法
l 参看w3c文档
