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 文档 "形 ...
随机推荐
- poj 1013(uva 608) Counterfeit Dollar
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #in ...
- ASP.NET - 自定义控件处理页面事件(控件与页面数据交互)的方法
//用委托的方法实现 //控件代码 public delegate void DelegateFunction( string sPageTitle ); private DelegateFuncti ...
- Flex之HTML5视频播放解决方案
Flex的video类对于视频播放在ios操作系统下表现出不兼容,采用调用ios源生播放器的思路,那么怎么调呢? 话说Html5 和Flex是竞争关系,这次利用Html5的video标签实现ios播放 ...
- 马丁 福勒 Martin Fowler 关于依赖注入和反转控制的区别
马丁 福勒 Martin Fowler 关于依赖注入和反转控制的区别 http://martinfowler.com/articles/injection.html 中文翻译:http://files ...
- PHP使用hash_algos函数计算哈希值,之间的性能排序
PHP从5.1.2版本以上开始支持hash_algos函数,看这个名字就知道了,algos在英文中也表示算法的意思,hash_algos就是哈希算法,收集了一些常用的哈希算法,从5.1.2开始不同版本 ...
- Sublime Text3常用插件以及安装方法(实用)
Package Control组件在线安装 按Ctrl+`调出console(注:避免热键冲突) 粘贴以下代码到命令行并回车: import urllib.request,os; pf = 'Pack ...
- 下一个项目为什么要用 SLF4J
阿里巴巴 Java 开发手册 前几天阿里巴巴在云栖社区首次公开阿里官方Java代码规范标准,就是一个PDF手册,有命名规范,让你知道自己原来取的每一个类名.变量名都是烂名字,真替你家未来孩子担心:有集 ...
- 纯js实现html转pdf
项目开发中遇到了一个变态需求,需要把一整个页面导出为pdf格式,而且要保留页面上的所有的表格.svg图片和样式.简而言之,就是希望像截图一样,把整个页面截下来,然后保存成pdf.咋不上天呢--查了一下 ...
- mdadm命令详解及实验过程
一.概念 mdadm是multiple devices admin的简称,它是Linux下的一款标准的软件 RAID 管理工具,作者是Neil Brown 二.特点 mdadm能够诊断.监控和收集详细 ...
- IE兼容问题及处理
1.在IE6下,子元素能撑开父级设置好的宽高 2.IE6下的最小高度,高度小于19px的元素在IE6下会被当做19px来处理 解决办法:overflow:hidden; 3.IE6下 不支持1px的点 ...