xml基础之二(XML结构【2】)DTD文档模版
xml基础之二(XML结构【2】)DTD文档模版
我们知道XML主要用于数据的存储和传输,所以无论是自定义还是外部引用DTD模板文档,都是为了突出数据的存储规范。DTD(文档模板)是预先使用合法元素定义好的文档结构,用于给XML文件编写提供模板,即引用该某种DTD文档后,XML文档必须按照其结构进行编写,否则出错。DTD模板现在正被schema模式代替,在此我们对DTD大致了解一下,方便对schema模式进行学习。
1.DTD声明的形式
DTD可以声明在XML文档中;也可以在外部声明,然后在XML进行引用。
外部DTD文档复用性高,不像内部DTD仅用于某一文档的验证,推荐使用外部DTD定义。
使用DTD可预先定义好XML文档结构:
1.提供开发模板方便开发
2.对数据交互有清晰的了解,从而控制开发流程。
- 内部声明
如若DTD被声明在XML源文件中,它的位置应处于文档声明以及XML元素/结点声明之间
<?xml version="1.0" encoding="ISO-8859-1"?> <!--文档声明-->
<!--DTD声明-->
<! DOCTYPE 根元素 [结点声明]>
<node> <!--结点声明-->
<child>
<!--更多子结点-->
</child>
</node>
范例
<?xml version="1.0" encoding="ISO-8859-1"?> <!--文档声明/定义-->
<!--<! DOCTYPE 根元素 [结点声明]>-->
<!--<!ELEMENT xx type> 声明/定义某个结点的类型-->
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
- 外部声明,内部引用
使用软件编写DTD,然后在XML文件中进行引用,引用格式如下:
<!--在XML中使用DTD,编码格式一般为UTF-8,如果编码为IOS-8859-1,则为西方文字存储格式,不适用象形文字,如果文档出现中文会乱码-->
<?xml version="1.0" encoding="UTF-8"?> <!--文档声明-->
<!-- ! DOCTYPE 根结点 SYSTEM "引用DTD文件名"-->
<! DOCTYPE 根结点 SYSTEM "引用DTD文件名">
<node> <!--结点声明-->
<child>
<!--更多子结点-->
</child>
</node>
范例
<!--该DTD模板名为myNode-->
<!ELEMENT> node(child,subchild)>
<!ELEMENT child (#PCDATA)>
<!ELEMENT subchild (#PCDATA)>
<?xml version="1.0" encoding="ISO-8859-1"?> <!--文档声明,请注意encoding,与UTF-8对比-->
<!DOCTYPE node SYSTEM "myNode">
<node>
<child>
<subchild>
</subchild>
<child>
</node>
2.DTD模板内的XML模块结构
我们在https://www.cnblogs.com/singledogpro/p/9644125.html 对XML结构进行了笼统地介绍,再次对该结构进行细致地描述。
我们可以将XML结构分为5个模块,分别是元素,属性,实体,PCDATA(可解析替换的数据)和CDATA。
1.回顾上面的知识点,可知元素【被包裹在开始标签和结束标签的内容】可为空,也可含文本和其他模块。
<node></node> <!--空元素-->
<node id="1"></node> <!--含属性的元素-->
<node>i'm a node</node> <!--含文本的元素-->
2.能为元素提供额外的信息就被称为属性。属性都放在开始标签内,以键/值的形式存在。
<node id="1"></node> <!--node标签内含属性,属性键为id,值为1-->
3.实体其实概念和字符串常量一样,在另一个文件中定义了一个变量等于某个字符串,然后在XML中就可以直接使用此变量了。这个变量就叫做实体。比如XML系统文件内的5个自定义的变量/实体引用。在某个文件内定义某个变量/实体等于某个字符串,如变量 ;lgt
=">".当文档被 XML 解析器解析时,实体就会被展开,将XML的元素替换成一个文件内的字符串常量的过程叫实体展开。
| > | > | great than |
| < | < | less than |
| & | & | ampersand |
| ' | ' | apostrophe |
| " | '' | quotation mark |
4.PCDATA和CDATA,PCDATA是元素类型,CDATA是属性类型,在属性定义时,属性文本可想象为 XML 元素的开始标签与结束标签之间的文本,这些文本将被解析器检查实体以及标记,文本中的标签会被当作标记来处理,而实体会被展开。由于某些字符被系统占用了,如小于号"<",为了能在文本中正确显示小于号,只能拼凑一段字母来代表其意义。
<!--<!ELEMENT 元素名(#PCDATA)>-->
<node> a root node</node> <!--PCDATA-->
<!--<!ATTLIST 元素名 属性名 CDATA>-->
<node id="1"> root的ID为1 </node>
3.DTD模板内的XML元素声明
要知道元素分为根元素和子元素两大类,根元素声明包括定义子元素的个数和次序。
DTD文档的元素声明语法其中ELMENT为关键字,必须大写,elementName指代元素名,elementType为元素类型。
<!ELEMENT elementName elementType>
元素类型 | 类型描述 | 语法 | 表现形式 |
EMPTY | 空元素,即该元素没有子元素和文本,指示该元素为最小子元素简写为</元素名> | <!ELEMENT a EMPTY> | </a> |
ANY | 该类型元素没有任何定义限制,即可元素个数和次序随意编写,不推荐使用 | <!LLEMENT a ANY> | |
#PCDATA | 该元素仅含文本,没有子元素 | <!LLEMENT a (#PCDATA)> | <a>元素文本</a> |
纯元素类型 | 与#PCDATA相反,该元素类型仅含子元素,不含文本,但子元素可含文本 |
<a> <b>元素文本</b>
</a> |
|
元素修饰符 | 对元素的出现次数进行限定 | 详见子元素声明 |
1.根元素声明
<!--以!ELEMENT开头,跟着根元素名 ,再跟着子元素列表,该列表决定了子元素的出现顺序不可乱-->
<!ELEMENT 根元素/结点 (子元素列表)> <!--根元素声明语法 三个模块之间用空格隔开-->
<!ELEMENT root (head,body,foot)> <!--根元素实例-->
2.子元素声明
子元素声明有2种格式,一种还有子元素的,一种没有子元素的。有子元素的子元素声明与根元素声明类似,没有子元素的,声明其元素类型,为空(empty),为可解析数据(PCDATA),为仅出现一次的元素(子元素名称),为最少出现一次的元素(子元素名称+),或者出现或者不出现的元素(子元素名称*
)等以及要么出现A这个要么出现B的(A|B);
<!--子元素声明有2种格式,一种还有子元素的,一种没有子元素的-->
<!ELEMENT 根元素/结点 (子元素列表)> <!--有子元素的子元素声明,与根元素声明类似-->
<!ELEMENT root (head,body,foot)> <!--给定某个根元素序列-->
<!ELEMENT head (eye,ear,nose,mouth)>
有子元素的子元素声明
<root> <!--根元素结点-->
<head><!--子元素结点-->
<eye><!--子元素的子元素结点-->
</eye>
<ear><!--子元素的子元素结点-->
</ear>
<nose><!--子元素的子元素结点-->
</nose>
<mouth><!--子元素的子元素结点-->
</mouth>
</head>
</root>
<!ELEMENT 根元素/结点 (子元素类别)> <!--没有子元素的子元素声明,括号内为元素类别-->
<!ELEMENT head (eye,ear,nose,mouth)><!--给定某个根元素序列-->
<!ELEMENT eye (#PCDATA)>
没有子元素的子元素声明实例
<head><!--子元素结点-->
<eye><!--子元素的子元素结点-->
这是眼睛
</eye>
</head>
4.属性
XML元素内包含属性,所以DTD内属性也需要声明。关键字ATTLIST全部要大写,attribute list(属性列表)简化为ATT LIST。
<!ATTLIST 元素名 属性键/属性名 属性类型 默认属性值> <!--某元素结点的属性DTD声明格式-->
<!ATTLIST head decription CDATA "这是头" >
<!--头元素结点的属性XML案例-->
<head description ="这是头">
上述DTD模板文档定义了头的概念。然后在XML文档对其进行复用。其中属性类型由系统提供,常用的为CDATA,ID,ENTITY以及xml:默认属性值是DTD文件默认值,在XML文件中可进行修改,上述关于头的XML案例,也可修改为<head description ="动物的核心部件">
。
该默认值也可使用属性约束符,如#REQUIRED(属性值是必需的,不能为空),#IMPLIED(属性不是必需的,可以为空),#FIXED value(属性值是固定的,不能被修改)
<!--属性定义语法-->
<!ATTLIST 元素名称 属性名称 属性类型 #FIXED "value">
<!ATTLIST 元素名称 属性名称 属性类型 #IMPLIED>
<!ATTLIST 元素名称 属性名称 属性类型 #REQUIRED>
<!--DTD文档属性定义-->
<!ATTLIST student id CDATA #REQUIRED>
<!ATTLIST connection phoneNumber CDATA #IMPLIED>
<!ATTLIST connection address CDATA #FIXED "xx村">
<!--XML实现-->
<student id="440xxxx">
<connection phoneNumber ="020-xxxx">
<connection address="xx村">
上述描述了一个(固定的属性)身份证号的人,他住在(必需的属性)xx村,可有可没有电话号码.即在DTD文档内进行约束定义,在XML进行实现。可想象成定义公民的权力和义务,一般公民有选举权,犯罪人员可能被剥夺了政治权,还需要劳动改造。
5.变量/实体声明
我们可以完全将实体当作是变量。它的声明也有2种。一种是在XML内部声明,另一种是在DTD(模板文件)声明。假设仓库/数据库内有一本Book叫Code,它的Price是9.9元。那么我们就有2个实体变量Book和Price.其值为Code和9.9,要用双引或单引号包裹。要它在商城显示为书名和价格。
<!ENTITY 变量名 变量值> <!--XML文件内部变量声明-->
<!ENTITY Book "Code">
<!ENTITY Price "9.9">
<!--XML文件内使用,一个变量的引用由3部分组成,一个和号 (&), 一个变量名, 以及一个分号 (;)-->
<BookStore>
&Book;&Price;
</BookStore>
<!ENTITY 变量名 SYSTEM "url"> <!--外部声明,声明变量Book,它的声明来源为某个网站的DTD文件-->
<!ENTITY Book SYSTEM "http://www.taobao.com/dtd/entities.dtd".>
<!ENTITY Price SYSTEM "http://www.taobao.com/dtd/entities.dtd".>
<!--与XML文件内使用相-->
<BookStore>
&Book;&Price;
</BookStore>
6.自定义的DTD文档
这里我们尝试定义下头的DTD文档,以及XML案例,这里要注意下格式,变量/实体声明要放在元素之前,属性声明放在元素之后。
<!--DTD文档-->
<!DOCTYPE root [
<!--变量/实体声明要放在元素之前,此处为空-->
<!ELEMENT root (head,body,foot)> <!--给定根元素的序列-->
<!ELEMENT head (eye,ear,nose,mouth)><!--给定子元素'头'的序列-->
<!ELEMENT eye (#PCDATA)> <!--子元素没有子元素,只有文本-->
<!ATTLIS root decription CDATA "简单展示"> <!--属性放在元素声明之后-->
]>
<!--外部引用XML文档-->
<root decription=“简单展示”>
<head><!--子元素结点-->
<eye><!--子元素的子元素结点-->
这是眼睛
</eye>
</head>
</root>
7.总结
DTD可称为XML文件的模板文档,但由于它不支持数据类型和命名空间,没有Schema(XML模型)的扩展性好,所以逐渐被schema替代。下个章节将介绍Schema,XML模型。它与DTD类似。