在web开发中每天都会看到这样的代码:
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
——————分界线——————
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
大概能猜到DTD或xsd都是引入的一种格式规范,那么具体是怎样的呢?
注意:本文只对两种文档做简单介绍,不涉及如何编写DTD,如何编写schema(.xsd)。且大部分资料来自W3CSchool,如果想知道如何编写这些文档及更细节的东西,请直接访问:
DTD:http://www.w3school.com.cn/dtd/index.asp
schema:http://www.w3school.com.cn/schema/index.asp
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。
简单来说,dtd文档定义了当前xml文件中的标签层次,可以有哪些标签,标签可以有哪些属性。
dtd文档和很多其他文件一样可以内嵌或外链,内嵌的格式我们基本看不到了,而且外链的话基本也是使用大家公用的定义好的dtd文档。下面代码是一个dtd文档样例:
note.dtd:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
其中:
!ELEMENT note定义 note 元素有四个元素:"to、from、heading,、body"
!ELEMENT to定义 to 元素为 "#PCDATA" 类型
!ELEMENT from定义 from 元素为 "#PCDATA" 类型
!ELEMENT heading定义 heading 元素为 "#PCDATA" 类型
!ELEMENT body定义 body 元素为 "#PCDATA" 类型 至于#PCDATA等类型具体是怎样的,有兴趣自行了解吧
现在你可以去查看文章头部提到的见过无数次的mybatis相关dtd的定义了:
点击下面的网址可以直接查看或下载mybatis-3-config.dtd,-mapper.dtd
http://mybatis.org/dtd/mybatis-3-config.dtd http://mybatis.org/dtd/mybatis-3-mapper.dtd
举个例子,在mybatis-3-config.dtd文档中有如下定义:
<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?
, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?
, databaseIdProvider?, mappers?)>
该定义表明根元素configuration包括了哪些元素,?表示元素可选。。具体的就不管了
dtd的缺点(最为明显的两点):
DTD不遵守XML语法(写XML文档实例时候用一种语法,写DTD的时候用另外一种语法)
不支持命名空间 (括号里的这段话是我的猜测,可以忽略:如果要引用a.dtd中的a,b.dtd中的b,但是a.dtd/b.dtd中都定义了c,就会冲突。不过不会出现这样的问题,一个xml文件只对应一个dtd[貌似是更大的麻烦])
上面两个缺点恰好是schema的优点
XML Schema 是基于 XML 的 DTD 替代者。
XML Schema 可描述 XML 文档的结构。
XML Schema 语言也可作为 XSD(XML Schema Definition)来引用。
回到开头处的代码:
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 表示xsi可以作为一个命名空间来使用,可以理解成final int Pi;
xmlns="http://xmlns.jcp.org/xml/ns/javaee" 表示默认的xml namespace的取值
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 表示xsi命名空间的取值,可以理解为 Pi=3.14;
这也就是说如果我把web.xml中的所有xsi重命名为myxsi也不会出问题,为此我做了一下测试:
我打开了久违的AndroidStudio(因为依稀记得AS中用到xmlns的地方特别多,且正在学习的java项目中配置文件被spring自动管理了找不着。。)
如图所示我运行了一个app:
在确认应用能跑之后我把上图中所有的tool改成了mytool,并且将符号左边的android改成了xsdtest。
在我兴致勃勃的重新运行的时候却出了bug——error: unbound prefix。
但是注意到这里的写法和我们上面讲的写法不一样,有可能安卓内部有什么优化。所以没有成功吧,如代码区所示
注意到这里引用格式和我们的说的并不相同,按照我们所说的格式应修改成如下:
xmlns:xsdtest="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mytools="http://www.w3.org/2001/XMLSchema-instance"
xsdtest:schemaLocation="~~~~~.xsd"
mytools:schemaLocation="~~~~~.xsd">//因为我并不知道对应的xsd在哪里
。。不行,我确实不能以unbound prefix作为本文的结束。。所以我打开了一个maven项目,在最外层pom下有如下定义:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
我试着将xsi改成xsdtest然后运行项目,如下:
在postman上查看这个后台项目的返回值,成功得到结果(和原本用xmlns:sxi一致)
。。schema命名空间验证小测试到此结束。。
总结:
和文章开始说的一样,在很多xml头部引入的dtd,xsd文档用于指明当前文件的规范。
吐槽——为了一个小验证,,花了我两个小时。。我的初衷只是记录下原本觉得奇怪的dtd,xsd