Java使用Schema模式对XML验证
XML允许创作者定义自己的标签,因其灵活的特性让其难以编写和解析。因此必须使用某种模式来约束其结构。目前最流行的这种模式有两种:DTD和SCHEMA,而后者以其独特的优势即将取代DTD模式,目前只是过渡时期。XML教程请参考这里。
为什么要用Schema
DTD 的局限性
- DTD不遵守XML语法(写XML文档实例时候用一种语法,写DTD的时候用另外一种语法)
- DTD数据类型有限(与数据库数据类型不一致)
- DTD不可扩展
- DTD不支持命名空间(命名冲突)
.Schema的新特性
- Schema基于XML语法
- Schema可以用能处理XML文档的工具处理
- Schema大大扩充了数据类型,可以自定义数据类型
- Schema支持元素的继承—Object-Oriented’
- Schema支持属性组
每设计一个模式(DTD或Schema),都对应一种新的标记语言,比如使用xhtml1-strict.dtd诞生了html。基于DTD即将被Schema取代,本篇只讨论Schema模式。Schema教程请参考这里。
Schema验证XML
note.xml(d:\MyTemp\xml\note.xml)
<?xml version="1.0"?>
<note xmlns="http://www.oseye.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.oseye.net note.xsd"> <to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
note.xsd(d:\MyTemp\xml\note.xsd)
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.oseye.net" xmlns="http://www.oseye.net"
elementFormDefault="qualified"> <xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="to" type="xs:string" />
<xs:element name="from" type="xs:string" />
<xs:element name="heading" type="xs:string" />
<xs:element name="body" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
代码解释:
xmlns:xs="http://www.w3.org/2001/XMLSchema"
显示 schema 中用到的元素和数据类型来自命名空间 "http://www.w3.org/2001/XMLSchema"。同时它还规定了来自命名空间 "http://www.w3.org/2001/XMLSchema" 的元素和数据类型应该使用前缀 xs。
targetNamespace="http://www.oseye.net"
显示被此 schema 定义的元素 (note, to, from, heading, body) 来自命名空间: "http://www.oseye.net"。
xmlns="http://www.oseye.net"
指出默认的命名空间是 "http://www.oseye.net"。
elementFormDefault="qualified"
指出任何 XML 实例文档所使用的且在此 schema 中声明过的元素必须被命名空间限定。
App.java
package net.oseye.SchemaXML; import java.io.File; import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator; import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* xml的schema验证器
* @author oseye.net
*/
public class App {
public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.out.print("usage:cmd xsdfile xmlfile");
System.exit(0);
}
SchemaFactory schemaFactory = SchemaFactory
.newInstance("http://www.w3.org/2001/XMLSchema"); Schema schema = schemaFactory.newSchema(new File(args[0]));
Validator validator = schema.newValidator();
validator.setErrorHandler(new ErrorHandler() { public void warning(SAXParseException exception)
throws SAXException {
System.out.println("警告:" + exception);
} public void fatalError(SAXParseException exception)
throws SAXException {
System.out.println("致命:" + exception);
} public void error(SAXParseException exception) throws SAXException {
System.out.println("错误:" + exception); }
});
validator.validate(new StreamSource(new File(args[1])));
}
}
PS:你或许对“SchemaFactory.newInstance(String schemaLanguage) ”的参数模式语言有疑问,这里摘录JDK文档中的描述:
模式语言
此规范使用名称空间 URI 来指定模式语言。下表显示了此规范定义的值。
要遵守此规范,实现只需支持 W3C XML 模式 1.0 即可。但是,如果实现选择支持其他模式语言,那么它必须遵守此规范中所描述的相关行为。
此处未列出的模式语言应引用它们自己的 URI 来表示它们本身。SchemaFactory 类能够在运行时定位其他模式语言的其他实现。
注意,因为 XML DTD 与解析过程有紧密联系,并对解析过程产生很大影响,因此不能将 DTD 验证定义为与解析无关的过程。出于此原因,此规范不定义 XML DTD 的语义。这并不限制实现者以他们了解的合适方式来实现它,但这里提醒用户,此接口上实现的任何 DTD 验证必然偏离 XML 1.0 中所定义的 XML DTD 语义。
值:XMLConstants.W3C_XML_SCHEMA_NS_URI ("http://www.w3.org/2001/XMLSchema"),表示的语言是:W3C XML Schema 1.0;
值:XMLConstants.RELAXNG_NS_URI ("http://relaxng.org/ns/structure/1.0"),表示的语言是:RELAX NG 1.0;
执行
java net.oseye.SchemaXML.App d:\MyTemp\xml\note.xsd d:\MyTemp\xml\note.xml
没有任何的输出,说明是验证通过的,如果我们把note.xml修改成这样:
<?xml version="1.0"?>
<note xmlns="http://www.oseye.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.oseye.net note.xsd"> <name>George</name>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
执行验证将输出:
错误:org.xml.sax.SAXParseException; systemId: file:/d:/MyTemp/xml/note.xml; lin
eNumber: 5; columnNumber: 8; cvc-complex-type.2.4.a: 发现了以元素 'name' 开头的
无效内容。应以 '{"http://www.oseye.net":to}' 之一开头。
你也能从中看到了to是使用了默认命名空间的作用。
命名空间
上面提到了命名,其实命名空间这个东东最难理解,难以理解的原因是因为它是URL,其实这个URL完全可以不用URL来表示,及时使用URL也完全可以是不可用的,因为它只是一个标示。标准建议使用URL,只是为了方便其唯一性。
上文说到,每设计一个模式(DTD或Schema),都对应一种新的标记语言。在各种各样的XML实例标记语言如雨后春笋般不断涌现的过程中,将会产生这样的一种应用需求,即在一个XML文档中,包含由多个DTD描述的元素。这个想法显然是达到“物尽其用”的一个好办法,它帮助我们最大程度低利用了现有的资源。
但是,这就造成了XML元素的冲突,如在一个XML文档中有两个table元素,而他们表达的含义却不同,前者表示表格,后者表示家具:
<?xml version="1.0"?>
<root>
<table>
<tr>
<td>Apples</td>
<td>Bananas</td>
</tr>
</table>
<table>
<name>African Coffee Table</name>
<width>80</width>
<length>120</length>
</table>
</root>
我们可以使用前缀来区分
<?xml version="1.0"?>
<root>
<h:table>
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<f:table>
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
</root>
前缀太简短,不易阅读,于是标准规定了命名空间来和前缀一同使用,既易阅读也不会太繁冗,名空间格式:
xmlns:namespace-prefix="namespaceURI"
当命名空间被定义在元素的开始标签中时,所有带有相同前缀的子元素都会与同一个命名空间相关联。
PS:用于标示命名空间的地址不会被解析器用于查找信息。其惟一的作用是赋予命名空间一个惟一的名称。不过,很多公司常常会作为指针来使用命名空间指向实际存在的网页,这个网页包含关于命名空间的信息。
<?xml version="1.0"?>
<root>
<h:table xmlns:h="http://www.w3.org/TR/html4/">
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<f:table xmlns:f="http://www.w3school.com.cn/furniture">
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
</root>
如果不使用前缀则是默认命名空间,命名空间有其作用域的,具体细节请参考XML文档。然后你可以定义一个XSD或多个XSD来验证此XML格式是否正确,如何编写XSD,请参考这里。
schemaLocation 属性 XML 架构实例命名空间 http://www.w3.org/2001/XMLSchema-instance(通常与前缀 xsi 关联)定义仅适用于 XML 实例文档而适用于 XML 架构文档区别于 XML 架构命名空间 http://www.w3.org/2001/XMLSchema 定义 schemaLocation 属性。
xsi:schemaLocation 属性提供种方法来查找 XML 实例文档定义命名空间 XML 架构定义值用空白分隔统资源标识符 (URI) 对列表其每对 URI 都依次包含命名空间及该命名空间 XML 架构定义(通常 .xsd 文件)位置
当 XML 文档反序列化对象时XmlSerializer 类忽略 xsi:schemaLocation 属性验证 XML 文档时XmlValidatingReader 类使用该属性值来获取 XML 架构定义
本文主要是针对《使用Spring构建RMI服务器和客户端》遇到问题后的延伸,如果你遇到了什么问题,欢迎留言交流。
Java使用Schema模式对XML验证的更多相关文章
- Java工具类——通过配置XML验证Map
Java工具类--通过配置XML验证Map 背景 在JavaWeb项目中,接收前端过来的参数时通常是使用我们的实体类进行接收的.但是呢,我们不能去决定已经搭建好的框架是怎么样的,在我接触的框架中有一种 ...
- java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】
java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...
- Java面试题 OOAD & UML+XML+SQL+JDBC & Hibernate
二.OOA/D 与UML 部分:(共6 题:基础2 道,中等难度4 道) 96.UML 是什么?常用的几种图?[基础] 答:UML 是标准建模语言:常用图包括:用例图,静态图(包括类图.对象图和包图) ...
- JAVA中使用DOM解析XML文件
XML是一种方便快捷高效的数据保存传输的格式,在JSON广泛使用之前,XML是服务器和客户端之间数据传输的主要方式.因此,需要使用各种方式,解析服务器传送过来的信息,以供使用者查看. JAVA作为一种 ...
- 一张图搞定Java设计模式——工厂模式! 就问你要不要学!
小编今天分享的内容是Java设计模式之工厂模式. 收藏之前,务必点个赞,这对小编能否在头条继续给大家分享Java的知识很重要,谢谢!文末有投票,你想了解Java的哪一部分内容,请反馈给我. 获取学习资 ...
- Java Web开发模式
一 Java Web开发模式的变迁 1 最初的Java web服务器端编程技术是Servlet,利用Servlet就可以开发出一个Web应用程序. 2 为了解决Servlet缺陷,SUN推出了JSP技 ...
- java责任链模式及项目实际运用
1.前言 上次我们认识了java责任链模式的设计,那么接下来将给大家展示责任链模式项目中的实际运用.如何快速搭建责任链模式的项目中运用. 2.简单技术准备 我们要在项目中使用借助这样的几个知识的组合运 ...
- Java的MVC模式简介
Java的MVC模式简介 MVC(Model View Control)模型-视图-控制器 首先我们需要知道MVC模式并不是javaweb项目中独有的,MVC是一种软件工程中的一种软件架构模式,把软件 ...
- 雷林鹏分享:XML 验证
XML 验证 拥有正确语法的 XML 被称为"形式良好"的 XML. 通过 DTD 验证的XML是"合法"的 XML. 形式良好的 XML 文档 "形 ...
随机推荐
- Intent的属性及Intent-filter配置——实例Action、Data属性启动系统Activity
一旦为Intent同时指定了Action.Data属性,那么Android将可根据指定的数据类型来启动特定的应用程序,并对指定数据类型执行相应的操作. 下面是几个Action属性.Data属性的组合. ...
- mybatis判断集合为空或者元素个数为零
mybatis判断集合为空或者元素个数为零: <if test="mlhs != null and mlhs.size() != 0"> and t.mlh_name ...
- 【.net 深呼吸】细说CodeDom(10):生成异常处理语句
写完这一篇,大概可以准备过年了,就算是这系列文章的收尾吧. 异常处理语句,就是常说的try...catch语句,有时候,也会带有finally子句.要生成异常处理语句,得用到CodeTryCatchF ...
- Eclipse安装git
用Eclipse开发,如果需要团队协作,git作为分布式版本管理工具就是个比较好的选择.下面简单介绍一下git插件的安装方法: 1.Help -- install new software 打开插件安 ...
- JavaScript中DOM的层次节点(一)
DOM是针对HTML和XML文档的一个API,描绘了一个层次化的节点树,允许开发人员添加.修改.删除节点的一部分. DOM将HTML和XML文档描绘成一个有多个节点构成的结构,节点分为12种不同的节点 ...
- Dev的WPF控件与VS2012不兼容问题
在只有vs2010环境下Dev的wpf可以在视图模式下显示,但是安装vs2012后无法打开界面的视图模式,报错:无法创建控件实例! 发现是Dev的wpf控件与.net framework 4.5不兼容 ...
- quagga源码学习--BGP协议路由更新
BGP的核心就是交换路由,所以关键的部分还是在路由的更新与撤销上面,这之间包含了冗长的属性,community等等处理过程,不做详述. bgp_read函数是路由更新的事件处理函数,在收到BGP_MS ...
- 工作总结之Git
工作中,终端数据的制作好后,使用的是SmartGit(注:Git的一个客户端)来push到服务器:但是出现了奇怪的现象: 1.git checkout到本地的目录,理论上目录下有包括新增,删除,变更在 ...
- Hadoop 的安装及配置
Linux RedHat--CentOs CentOs 6.4 Debian--Ubuntu VMware 虚拟机 关于虚拟机实现上网的解决办法 NAT: 网络地址转换 当 ...
- js实现淘宝首页图片轮播效果
原文:http://ce.sysu.edu.cn/hope2008/Education/ShowArticle.asp?ArticleID=10585 <!DOCTYPE html> &l ...