JAXP体验(二). DTD是什么?

XML基本

XML全称是Extensible Markup Language,可扩展标记语言,为啥不叫EML呢。 1993年诞生HTML,1998年出现XML。
HTML我们都熟,说说XML和HTML不一样的特点:1。没有预置标签,2。可以定义新的标记语言,扩展好,3。区分大小写,4。有语法要求

安利一款XML编辑器 XMLSpy。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <bean id="user" class="com.model.User" init-method="init">
    </bean>
</beans>

上述例子是我们大概率接触到的spring的xml配置文件,类似的还有mybatis的配置文件。两者都是XML,但是开头写法却不一样,其实这是XML的两种语义约束,格式约束 以及 语义约束。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <!-- 配置数据库连接信息 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
                <property name="username" value="root" />
                <property name="password" value="" />
            </dataSource>
        </environment>
    </environments>

</configuration>

XML从一方面可以分为三种:
1。格式不行,存在明显语法错误;
2。格式行,但是没有按照框架(就是XML语义约束)来写。
3。格式行,也按照语义约束来了。
这不就是我们高中写议论文的分类吗,高中语文老师都会给我们应试教育议论文的模板,先展示文采,话题发散,阐明观点,承上启下,例子证明,总结升华观点。
1花里胡哨,不按照模板来;2按照模板来了,(比如例子证明,某某某历史名人说过,多个朋友多条路?),这就不符合约束了;3按照模子,遵循约定。

从上可以得出结论:XML有两点约束:1.格式约束 2. 语义约束

XML的格式约束

XML的格式约束有几点:

  1. XML第一行是XML文档声明,
  2. XML有且只能有一个根节点
  3. XML的标签要么开始标签和结束标签配对,要么空标签出现, 标签不能出现混乱嵌套
  4. XML标签的属性不能单独出现
1.XML文档声明

XML第一行我们见都是<?xml version="1.0" ?>
这行的作用就是告诉这是一个XML文档,遵循XML文档规范的XML,version是必须的,通常都使用1.0
其实还有两个属性,
encoding: encoding只是告诉使用它的程序解码用的字符集。 本身我们书写XML还有一个编码,比如本地可能你会使用UTF-8或者GB2312编码,这个属性只是告诉外部解码该用什么字符集。
standalone: 声明该文档是否需要引用其他资源,只有yes|no。 这个我只见过。

2.XML的一个根节点

所谓一个根节点就是只能有一个根元素。如果像如下,是肯定不可以的。XML可以解析成树结构,如果多个根节点,那就是解析成森林了...

<?xml version="1.0" ?>
<Root>
   ......
</Root>
<Root2>
</Root2>

3.XML的标签

1.XML严格区分大小写。就必须配对出现,或者出现;
2. <x name="11"></x> XML的标签属性不能是空值,不能出现多个重名属性,不能像这样 <x name></x> 。这一样也和前端区别挺大,写前端的同学写XML要尤为注意。

3.XML标签中间的多个空格包括换行都会保留下来, 如果在XML标签中书写了特殊含义的字符(比如&),就会引起格式错误。比如<result> 1+1<2 </result>
XML遇到<号,认为是标签头,结果匹配不到结束标签,这样就格式错误了。 解决方案有两种:
1. 转义, <转义成 <
2. CDATA标记, ,原因是XML不会对CDATA里的内容做处理

  1. 允许XML处理指令,

XML的语义约束

XML的语义约束,作为java程序员肯定接触过,以两种框架来举例,Mybatis配置文件使用的就是DTD约束,Spring配置文件使用的就是XML Schema约束。JAVA和XML联系真的很多,java开发大多都接触过这两框架,
大多都写过这两配置文件。java跨平台,xml也没有平台之分。

1.DTD约束

DTD,Document Type Definition,文档类型定义的意思。
DTD约束有几层限制:文档可以出现的元素,文档的根元素类型,文档每个元素的顺序、次数、内容、结构,文档各个元素的属性(包括属性名、属性规则)
DTD约束主要用来验证符合语义约束的XML,不符合语义约束的配置文件没法处理,不按套路出牌的XML 我们的java程序没法解析。

1.1 DTD使用方式

DTD使用方式和JAVA超级像。JAVA引用变量方法,内部定义个static final变量,我们就能使用这个属性;外部类定义public static final,其他类中我们也可以访问到;
JAVA外部依赖定义的变量,比如web开发时候用到的各种常量,Spring中HttpMethod等。

DTD使用方式也是三种:

  1. 内部DTD
  2. 外部DTD
  3. 公共DTD
    这里的内部外部都是指我们书写的DTD的位置,XML文件内、XML文件外(本地相对路径或者 指向某个URI)。

DTD的语法是: <!DOCTYPE 根元素名称[ 元素描述 ]> ,DTD内容需要跟在XML声明后面
元素描述的语法是<!ELEMENT 元素名称 类别>
标准DTD语法的网站上是 https://www.w3school.com.cn/dtd/dtd_elements.asp。
以下面我写的DTD为例简单讲几个DTD语法:
文档的根元素在第3行定为Root,Root根元素第4行限制为包含body、div、p、a、span等若干次(*代表若干次,0次或者更多次,这里的body div是我随便定义的,和HTML没有任何关系),
#PCDATA是专有写法。第7行限制了a元素必须包含一个span标签。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Root[
<!ELEMENT Root (body|div|p|a|span)*>
<!ELEMENT body (#PCDATA|div|p|a|span)*>
<!ELEMENT div (#PCDATA|div|p|a|span)*>
<!ELEMENT p (#PCDATA|div|p|a|span)*>
<!ELEMENT a (span)>
<!ELEMENT span (#PCDATA|a|span)*>
]>
<Root>
</Root>
1.2 内部DTD

将上面写的语法紧跟在XML声明后面就是内部DTD, 没啥优点,缺点就是如果很多很多份XML要使用语义约束不太方便。

1.3 外部DTD

外部DTD的语法是:
<!DOCTYPE 根元素名 SYSTEM "URI" 此处的URI可以是绝对路径,也可以是相对路径。 外部DTD的写法就和内部DTD不太一样了。

上例中外部DTD改造成,可以看到去除了<!DOCTYPE Root[]>这个描述,只保留了元素描述的内容。另外外部DTD文件也有自己的XML声明,
说明DTD外部可以指定对外编码格式。

Root.dtd

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT Root (body|div|p|a|span)*>
<!ELEMENT body (#PCDATA|div|p|a|span)*>
<!ELEMENT div (#PCDATA|div|p|a|span)*>
<!ELEMENT p (#PCDATA|div|p|a|span)*>
<!ELEMENT a (span)>
<!ELEMENT span (#PCDATA|a|span)*>

引用Root.dtd文件的地方写法:这里是因为xml和DTD文件放在同一级目录,相对路径就能访问到。如果不在一个目录里,URI可以使用文件协议:
<!DOCTYPE Root SYSTEM "file:///f:/app/Root.dtd"> 这样也能访问到DTD文件的,其他多种协议http https更不用说。

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

1.3 公共DTD

这种DTD相当于某个组织约定的,使用语法如下:
<!DOCTYPE 根元素 PUBLIC "DTD标识名" "DTD的URI",可以看到和外部DTD的区别仅仅是public替换system,以及多了个DTD标识名。

以我们最常见的Mybatis为例,根元素确实是configuration,就是DTD标识名感觉写法独特, URI也是可以下载的。mybatis-3-config.dtd文件还挺长的,就不占篇幅了。
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

以mybatis 一小段dtd为例:
mappers元素可以包含任意个mapper,任意个package,但是 mapper和package是按照顺序来写的,如果package在mapper之前,那是不行的。
mapper是个空元素,只有三个属性 resource url class, #IMPLIED是属性默认值意思,#IMPLIED就是非必要的。 这下是不是对mybatis配置文件写法有了更清楚的认识。

<!ELEMENT mappers (mapper*,package*)>

<!ELEMENT mapper EMPTY>
<!ATTLIST mapper
resource CDATA #IMPLIED
url CDATA #IMPLIED
class CDATA #IMPLIED
>

<!ELEMENT package EMPTY>
<!ATTLIST package
name CDATA #REQUIRED
>

DTD的语法有很多,W3S上就能学习到很多https://www.w3school.com.cn/dtd/dtd_attributes.asp,这里就不画蛇添足复制了,因为我们很少会开发DTD,需要我们去掌握DTD语法,用不到呀。

posted @ 2020-12-27 20:25  喜欢日向雏田一样的女子啊  阅读(366)  评论(0编辑  收藏  举报