09月20, 2016

从doctype说开来

对大多数Web前端工程师来说,对HTML的doctype即熟悉又陌生。今天我们就八一八doctype相关的知识。

SGML、XML、HTML、XHTML的关系

说doctype之前先得说说这几个*ML之间的关系。

最先有的SGML,它是一个通用的标记语言。然后有了HTML,基于SGML,专门为Web页面而生。

XML是SGML的一个子集,更简单,也更严格。这里是W3C在1997年发的一个对XML和SGML的对比Note。

最后,基于XML重新制定了XHTML。 下图给出了4者之间的关系:

html-sgml-xhtml-xml

可以看出来,SGML和XML都是通用的标记语言。HTML和XHTML都是通用标记语言在Web领域的特定应用。既然是特定领域,就需要对可以出现的元素做出精确的定义。所以,就有了文档类型定义---DTD

文档类型定义-DTD

DTD定义了XML文档的结构。定义了合法的标签、属性等。HTML对应的DTD定义了HTML文档中可以出现的标签及其属性。

DTD超简介

想一想,作为DTD需要具备以下能力:定义合法元素、元素内可以包含的元素、元素的闭合;定义元素的属性必选、可选和取值。

声明元素:

<!ELEMENT generic-identifier (content or EMPTY)>

声明属性:

 <!ATTLIST element-name {attr-name attr-type default} ...>

default = [#REQUIRED | #IMPLIED | "value" | #FIXED "value"] 含义依次为:必填、可选、可选默认、必选固定

声明实体:

<!ENTITY % entity-name "text">

所有出现%entity-name;的地方都会被替换为text

(完整DTD教程)

下面是一个简单的DTD实例:

<?xml version="1.0"?>
<!DOCTYPE note [
  <!ELEMENT note    (to,from,heading,body)>
  <!ELEMENT to      (#PCDATA)>
  <!ELEMENT from    (#PCDATA)>
  <!ELEMENT heading (#PCDATA)>
  <!ELEMENT body    (#PCDATA)>
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don"t forget me this weekend!</body>
</note>

看,这里的<!DOCTYPE note...>是一个自定义的文档类型。 我们的html5的文档类型是<!DOCTYPE html>,是不是突然明白了什么?

上面的doctype note是内联的DTD。它定义了当前XML文件可以有一个note标签,其下可包含to,from,heading,body元素。这几个元素的内容都是PCDATA类型。

PCDATA(Parsed Character Data)将会被xml解析器parse,CDATA(Character Data)不会被parse。

再来看我们的HTML有哪些DTD:

HTML2.0

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

HTML3.2

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">

HTML2.0和3.2的doctype中并没有提供下载地址。不过我们也需要不关心了。 HTML4.01后都有提供dtd下载地址(下面省略了Frameset对应的doctype声明):

HTML4.01

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

HTML 4.01 Transitional

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

XHTML 1.0 Strict

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

XHTML 1.0 Transitional

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

XHTML 1.1

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

XHTML1.1及之前都是有对应dtd文件的。HTML5没有了。是不是突然感觉生活美好了、世界变清爽了!

HTML5

<!DOCTYPE html>

为什么没有html5.dtd或html5.xsd? 简单来说,html5已经不再是基于SGML或XML了,已经复杂到无法完全用DTD来描述了

不过经过搜索,我倒是还真找到了一些HTML的dtd:比如,html5.dtdKomodo Editor 中带的用来校验html5的dtd文件。

HTML5没有对应的DTD,但是XHTML1有啊,我们下载下来看看,里面都有什么!

XHTML1.dtd

将XHTML1.dtd下载下来。(XHTML1.1被分为多个模块,为了方便我们来看XHTML1.dtd) 整体浏览一下,发现前面是一些实体定义:

  1. Character mnemonic entities
  2. Imported Names
  3. Generic Attributes
  4. Text Elements
  5. Block level elements
  6. Content models for exclusions

后面被分为几个部分:

  1. Document Structure
  2. Document Head
  3. Document Body
  4. Paragraphs
  5. Headings
  6. Lists
  7. Address
  8. Horizontal Rule
  9. Preformatted Text
  10. Block-like Quotes
  11. Inserted/Deleted Text
  12. The Anchor Element
  13. Inline Elements
  14. Object
  15. Images
  16. Client-side image maps
  17. Forms
  18. Tables

从文档开头搜索<!ELEMENT,第一个就是html元素:

<!-- Document Structure -->
<!ELEMENT html (head, body)>
<!ATTLIST html
  %i18n;
  id          ID             #IMPLIED
  xmlns       %URI;          #FIXED "http://www.w3.org/1999/xhtml"
  >

html元素可以包含head和body元素,有id和xmlns属性。其中id可选,xmlns规定为http://www.w3.org/1999/xhtml

接下来看

<!-- Document Head  -->

<!ENTITY % head.misc "(script|style|meta|link|object)*">

<!-- content model is %head.misc; combined with a single
     title and an optional base element in any order -->

<!ELEMENT head (%head.misc;,
     ((title, %head.misc;, (base, %head.misc;)?) |
      (base, %head.misc;, (title, %head.misc;))))>

<!ATTLIST head
  %i18n;
  id          ID             #IMPLIED
  profile     %URI;          #IMPLIED
  >

如上面注释所说,head标签必须包含title,可选的base标签,若干可选的script、style、meta、link、object标签。

整个DTD文档中包含很多信息。比如,

通过搜索EMPTY>你可以找到所有自闭合标签:

<!ELEMENT base EMPTY>
<!ELEMENT meta EMPTY>
<!ELEMENT link EMPTY>
<!ELEMENT hr EMPTY>
<!ELEMENT br EMPTY>
<!ELEMENT param EMPTY>
<!ELEMENT img EMPTY>
<!ELEMENT area EMPTY>
<!ELEMENT input EMPTY>
<!ELEMENT col EMPTY>

通过搜索%Inline;>可以找到只允许包含内联元素的对象:

<!ELEMENT p %Inline;>
<!ELEMENT h1  %Inline;>
<!ELEMENT h2  %Inline;>
<!ELEMENT h3  %Inline;>
<!ELEMENT h4  %Inline;>
<!ELEMENT h5  %Inline;>
<!ELEMENT h6  %Inline;>
<!ELEMENT dt  %Inline;>
<!ELEMENT address  %Inline;>
<!ELEMENT span  %Inline;>
<!ELEMENT bdo  %Inline;>
<!ELEMENT em  %Inline;>
<!ELEMENT strong  %Inline;>
<!ELEMENT dfn  %Inline;>
<!ELEMENT code  %Inline;>
<!ELEMENT samp  %Inline;>
<!ELEMENT kbd  %Inline;>
<!ELEMENT var  %Inline;>
<!ELEMENT cite  %Inline;>
<!ELEMENT abbr  %Inline;>
<!ELEMENT acronym  %Inline;>
<!ELEMENT q  %Inline;>
<!ELEMENT sub  %Inline;>
<!ELEMENT sup  %Inline;>
<!ELEMENT tt  %Inline;>
<!ELEMENT i  %Inline;>
<!ELEMENT b  %Inline;>
<!ELEMENT big  %Inline;>
<!ELEMENT small  %Inline;>
<!ELEMENT label  %Inline;>
<!ELEMENT legend  %Inline;>
<!ELEMENT caption  %Inline;>

通过查看%Inline%Block)对应实体的内容,你可以知道有哪些元素是内联(快级)元素。

Java世界中的dtd(xsd)文件

Java世界中经常可以看到各种XML配置文件。XML之于Java就像JSON之于JavaScript。 这些XML都有对应的DTD文件或XSD。

比如: myBatis MapperServlet 的web.xml

Jave开发使用的的IDE多可以根据DTD(XSD)给出自动完成提示。不过,通过阅读DTD或XSD,我们还是可以从中发现很多有用的信息。其中的注释对我们理解对应框架的运行机制也是很有帮助的。

本文链接:http://aztack.wang/post/about-doctype.html

-- EOF--

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。