DTD的学习应用

DTD的学习应用

一、DTD概述

1、定义

DTD:Document Type Definition,翻译过来就是:文档类型定义 。它使用一系列元素来定义文档的结构,可以定义合法的XML文档结构。说白了就是一套规则。

2、为什么要有DTD

我觉得最重要的一点就是,有了DTD,每个XML文件就携带一个自身格式的描述,所谓格式描述就是我的XML文档里面可以写哪些东西,比如元素、属性、文本;

还有应用程序可以使用一个标准DTD校检从外部接收的XML数据是否有效。

二、DTD构建XML文档结构

DTD主要有两种声明方式:内部的DOCTYPE声明、外部的文档声明。

1、内部的DOCTYPE声明

在XML文档中直接声明,这个XML文档里面既包含XML定义,又包含DTD的定义。

<!DOCTYPE 根元素 [定义内容]>

示例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE people [
        <!ELEMENT people (man, woman)>
        <!ELEMENT man (#PCDATA)>
        <!ELEMENT woman (#PCDATA)>
        ]>

<people>
        <man>里斯</man>
        <woman>张三</woman>
</people>

这个[ ]里面是DTD的定义的内容。

2、外部的文档声明

所谓外部,就是DTD的定义和我们的XML文档是在不同的文件里面。就像我们的CSS样式文件和HTML分开一样

那么外部的DTD如何使用呢?

那就需要在XML文档的根元素的上面引入自定义DTD文件路径。

<!DOCTYPE 根元素 SYSTEM '自定义DTD文件路径'>

	引入DTD后,XML就会有固定的格式。

示例:

dtd文件

<?xml version="1.0" encoding="UTF-8" ?>

<!ELEMENT configuration (properties?, typeAliases?, mappers?)>

<!ELEMENT properties (property*)>
<!ATTLIST properties
resource CDATA #IMPLIED
url CDATA #IMPLIED
>

<!ELEMENT property EMPTY>
<!ATTLIST property
name CDATA #REQUIRED
value CDATA #REQUIRED
>

xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE people SYSTEM "config.dtd">

<configuration>
   <properties resource="jdbc.properties"/>
  <typeAliases>
        <package name="com.coldlight.domain"/>
    </typeAliases>
 </configuration>

三、DTD的结构定义

我们刚刚看了DTD构建XML文件结构的两种方式,他的作用主要就是用一些参数限制元素、属性和内容,

在工作中,我们使用外部DTD文档声明比较多,我们具体看一下外部申明中每个参数具体的作用:

1、元素的定义

**语法 :**元素声明有两种方式,区别是最后一位是类别还是元素内容

<!ELEMENT 元素名称 类别>
<!ELEMENT 元素名称 (元素内容)>

ELEMENT:就是关键字,固定写法;

元素名称:是指XML中元素的名称;

1.1、元素类别

通过第一种方式声明的:<!ELEMENT 元素名称 类别>,这里类别为下边左一栏标识的

类别举例描述
EMPTY<!ELEMENT 元素名称 EMPTY>该元素不能包含子元素和文本,但可以有属性
(#PCDATA)<!ELEMENT 元素名称 (#PCDATA)>可以包含任何字符数据,但是在其中不能包含任何子元素;
ANY<!ELEMENT 元素名称 ANY>该元素可以包含任何在DTD中定义的元素内容
(子元素名称)<!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.)>带一个或多个子元素的元素通过圆括号中的子元素名进行声明,只包含子元素,并且这些子元素外没有文本,子元素必须按照顺序出现在XML中
1.1.1、EMPTY

该元素不能包含子元素和文本,但可以有属性

<!ELEMENT property EMPTY>

正确:
<property name="username" value="root"/>

错误:不能包含文本和子元素
<property>李四</property>
<property>
	<node1><node1>
</property>
1.1.2、(#PCDATA)

可以包含任何字符数据,但是在其中不能包含任何子元素;

<ELEMENT note (#PCDATA)>

正确:
<note name="李四">23岁</note>

错误:不能包含子元素
<note>
	<node1><node1>
</note>
1.1.3、ANY

该元素可以包含任何在DTD中定义的元素内容

<!ELEMENT property ANY>

示例:
<property name="name">name</property>
<property>
	<name></name>
</property>

注意:将根元素设置为ANY后,元素出现的次数和顺序将不受限制。

1.1.4、子元素

带一个或多个子元素的元素通过圆括号中的子元素名进行声明,只包含子元素,并且这些子元素外没有文本,子元素必须按照顺序出现在XML中。除根元素设置为ANY除外。

<!ELEMENT typeAliases (typeAlias,package)>

示例:
<typeAliases>
<typeAlias></typeAlias>
<package></package>
</typeAliases>

通过第二种方式声明的:<!ELEMENT 元素名称 (元素内容)>,这里类别为下边左一栏标识的

类别举例描述
<!ELEMENT node (node1,node2)>元素必须按指定顺序出现,必须先出node1,再出现node2;
( )<!ELEMENT node (node1,node2)>用来给元素分组
<!ELEMENT node (node1|node2)>表示node1或者node2必须出现,两者必须出现一个。
*<!ELEMENT node (message*)>声明出现零次或多次的元素,message子元素可在node元素里出现零次或多次。
+<!ELEMENT node (message+)>声明最少出现一次的元素,message子元素至少在node元素里出现一次
?<!ELEMENT node (message?)>声明出现零次或一次的元素,message子元素可在node元素里出现零次或一次。

注意:+,*,?为基数操作符,若没有基数操作符,则表示必须有且仅有一个元素;

下面是mybatis-3-config.dtd的配置

<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>

这个是根元素的配置,根元素的名称为:configuration,里面包含properties、settings......等子元素。且在XML中,子元素必须按照当前的顺序,且每个资源子只能出现0次或一次。
2、属性的定义

语法:

<!ATTLIST 元素名称
属性名称 属性类型 属性特点
>

元素名称:所属元素的名称。

属性名称:自定义

2.1、属性类型
2.1.1、CDATA

CDATA是表示属性的值,可以是任何字符,这里包括数字和中文。

例如:

<!ELEMENT property EMPTY>
<!ATTLIST property
name CDATA #REQUIRED
value CDATA #REQUIRED
>

<payment name = "username" value="root"/>
<payment name = "password" value="123456"/>
2.1.2、ID

表明该属性的取值必须是唯一的。

<!ELEMENT property EMPTY>
<!ATTLIST property
name ID #REQUIRED
value CDATA #REQUIRED
>

正确:
<payment name = "username" value="root"/>
<payment name = "password" value="123456"/>

错误:
两个name不唯一了
<payment name = "username" value="root"/>
<payment name = "username" value="123456"/>
2.1. 3、Enumerated

枚举,预先定义了一些值,属性的值必须在所列出的值的范围内;

<!ELEMENT property EMPTY>
<!ATTLIST property
name ("username" | "password") #REQUIRED
value CDATA #REQUIRED
>
2.2、属性特点
2.2.1、#REQUIRED

它表示元素的所有的实例都必须有该属性的值(NOT NULL)

<!ATTLIST if
test CDATA #REQUIRED
>

示例:test参数不可为空

select * from  sys_user
where 1 = 1 
<if test="id != null">
 AND id =  #{id}
</if>
2.2.2、#IMPLIED

这就表示该属性的值是可以被忽略的。

<!ATTLIST select
id CDATA #REQUIRED
parameterMap CDATA #IMPLIED
resultType CDATA #IMPLIED
......
resultSets CDATA #IMPLIED 
>

示例:添加了#IMPLIED的参数可以忽略不写
<select id="getUser" resultType = "int">
select count(id) from sys_user 
</select>
2.2.3、#FIXED

元素中该属性的值必须为指定的固定值。

<!ELEMENT property EMPTY>
<!ATTLIST property
name CADATA #FIXED "username"
value CDATA #REQUIRED
>

# 只能为固定值
<payment  type = "username" />
2.2.4、Default

为属性提供一个默认的值。

四、实战练习

简单的学习了一下DTD的基础,那么我们也可以写出一些DTD,来构建XML文档结构了,下面我们有一个简单的练习:

用DTD构建一个XML文件结构,XML文档中的结构如下:

1、根元素为 mapper,包含namespace属性,属性为任意字符,且非必填项;

2、根元素下面有子元素:selectsql,且子元素必须要出现一个,且每个出现零次或者多次;

3、select元素要求:必须包含任何字符的id 属性,可以包含属性:parameterMapparameterTyperesultMapresultType,四个 参数可以为任何字符类型,且可以被忽略;可以包含include元素,元素可以出现多次;

4、sql元素要求:可以不包含任何子元素、也可以包含includewhereif四个参数任意;

练习DTD:

<!ELEMENT mapper (sql* | select*)+>

<!ATTLIST mapper
namespace CDATA #IMPLIED
>

<!ELEMENT select (#PCDATA | include)* >

<!ATTLIST select
id CDATA #REQUIRED
parameterMap CDATA #IMPLIED
parameterType CDATA #IMPLIED
resultMap CDATA #IMPLIED
resultType CDATA #IMPLIED
>

<!ELEMENT sql (#PCDATA | include| where | if )*>

解析:

<!ELEMENT mapper (select* | sql* )+>
<!--
根元素为mapper,下面有两个子元素:select和sql 
select*:表示出现零次或多次的
(select* | sql* )+ : +表示()里面的声明子元素必须出现一次;
-->

<!ATTLIST mapper
namespace CDATA #IMPLIED
>
<!--
mapper中包含namespace属性;
CDATA : 属性为任意字符;
#IMPLIED : 表示该属性的值是可以被忽略的
-->

<!ELEMENT select (#PCDATA | include)* >
<!--
select中可以包含includ元素,或者不包含任何子元素
* :可以出现0次或多次
-->

<!ATTLIST select
id CDATA #REQUIRED
parameterMap CDATA #IMPLIED
parameterType CDATA #IMPLIED
resultMap CDATA #IMPLIED
resultType CDATA #IMPLIED
>

<!ELEMENT sql (#PCDATA | include| where | if )*>

xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper SYSTEM "mybatis-3-mapper.dtd">
<mapper namespace="com.coldlight.mapper.SysUserMapper">

<sql id="restMap">
        id ,user_account AS accountName, nick_name AS nickName, mobile As phone
</sql>

    <select id="getUserById" parameterType="long" resultType="user">
        SELECT <include refid="restMap"/> FROM sys_user where id = #{id}
    </select>

</mapper>

五、总结回顾

1、总结回顾
  • DTD Document Type Definition 文档类型定义;
  • 它使用一系列元素来定义文档的结构,给XML文件就携带一个自身格式的描述;
  • 被多个XML共享,保持统一的数据交换格式,不同组织的人使用同一个通用的DTD来交换数据;
  • 应用程序可以使用一个标准DTD效验从外部世界接受来的XML数据是否有效
2、思考一下

我门通过学习和实战书写DTD,我们可以思考一下,DTD有没有缺陷:

1、DTD与XML不是一样的语法,我们写DTD的时候,还得去了解DTD的书写语法,比较麻烦;

2、DTD的数据类型有限,与我们的Java中基本数据类型不一致;

3、扩展性比较差;

我们看,DTD有这么多缺陷,我们有没有可以取代DTD的技术呢?

肯定是有的,就是Shema。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值