zoukankan      html  css  js  c++  java
  • 给XML文件定义DTD

    DTD是Document Type Definition(文档类型定义)的缩写。它通过定义元素、属性、标记以及文档中的实体及其相互关系等规则来保证XML文档的合法性。

    1.DTD的声明方式分为内部声明与外部声明

    内部声明的格式是:

    <!DOCTYPE 根元素 [
    
    <!ELEMENT 根元素 (元素1,元素2)>
    
    <!ELEMENT 元素1 (#PCDATA)>
    
    <!ELEMENT 元素2 (#PCDATA)>
    
    ]>

    外部声明的格式分两种,对应的关键字为"SYSTEM"与"PUBLIC"

    <!DOCTYPE 根元素 SYSTEM "外部DTD文件">
    
    <!-- 这里的外部DTD文件,若不指明 绝对路径,则必须是和xml文件在同一目录,否则无效 --> 

    "PUBLIC"声明的DTD文件通常是一个由权威机构制订的,提供给特定行业或公众使用的DTD

    <!DOCTYPE 根元素 PUBLIC "外部DTD的标示名" "外部DTD文件路径">

    2.元素类型声明 

    <!ELEMENT 元素名 元素内容描述>

    DTD中使用的元素内容类型有:EMPTY、ANY、Mixed、Elements

    EMPTY是指元素不能有任何的内容,但可以有属性:

    <!-- DTD声明部分 --> 
    
    <!ELEMENT 元素1 EMPTY>
    
    <!ATTLIST 元素1 性别 (男|女) "男"> 
    
    <!-- XML文件部分 -->
    
    <元素1 性别="女" /> 
    
    <!-- 这里若是以<元素1></元素1>的形式出现,即使里面没有任何数据,也会产生错误 -->

    ANY说明元素可以有任何类型的子元素,也可以是纯文本,还可以为空

    <!ELEMENT 元素2 ANY> 

    这里需要特别注意的是,虽然用ANY定义的元素可以包含其它元素,但必须遵循XML文件的"有效的"原则,即XML文件规定文件中所使用的任何元素都必须在DTD中给出定义。

    看下面这段非法的文件:

    <?xml version="1.0" encoding="gb2312"?>
    
    <!DOCTYPE 图书信息 [
    
    <!ELEMENT 图书信息 ANY>
    
    ]>
    
    <图书信息>
    
    <书名>新概念英语</书名>
    
    </图书信息>

    编译器会提示这样一条错误信息:

    "This file is not valid: Element '书名' has not been declared."

    就是提示"书名"这个元素没有经过定义,要纠正这个错误,只要在DTD定义部分加入定义语句"<!ELEMENT 书名 (#PCDATA)>"就可以了。

    Mixed允许混合内容使得字符数据和其他元素能在元素内共存,它并不是以关键字的形式存在的:

    <!ELEMENT 元素3 (#PCDATA|子元素1|子元素2)>
    <?xml version="1.0" encoding="gb2312"?>
    
    <!DOCTYPE 图书信息 [
    <!ELEMENT 图书信息 (#PCDATA|书名|价格)*>
    <!ELEMENT 书名 (#PCDATA)>
    <!ELEMENT 价格 (#PCDATA)>
    ]>
    
    <图书信息>
    今日新到图书:
    <书名>
    XML实用教程
    </书名>
    <价格>
    ¥26.00
    </价格>
    </图书信息>

    Elements规定特定子元素必须按规则与顺序出现,子元素后可以用各种元字符来说明出现的次数。

    <!ELEMENT 元素4 (子元素1,子元素2,子元素3)>

    可能出现的元字符:

    元字符 含义
    + 出现1次或多次
    * 出现0次或多次
    ? 出现0次或1次
    无符号 只能出现1次

    下面的例子中,"IT求职"的各项子元素必须按顺序和元字符说明的次数来出现:

    <?xml version="1.0" encoding="gb2312"?>
    
    <!DOCTYPE IT求职 [
    <!ELEMENT IT求职 (招聘信息)+>
    <!ELEMENT 招聘信息 (公司名,招聘职位+,公司网站?,联系方式*)>
    <!ELEMENT 公司名 (#PCDATA)>
    <!ELEMENT 招聘职位 (#PCDATA)>
    <!ELEMENT 公司网站 (#PCDATA)>
    <!ELEMENT 联系方式 (#PCDATA)>
    ]>
    
    <IT求职>
    
    <招聘信息>
    <公司名>中兴通讯</公司名>
    <!--这里招聘职位出现了2次-->
    <招聘职位>1.Java高级工程师</招聘职位>
    <招聘职位>2.C++高级工程师</招聘职位>
    <!--这里公司网站出现了1次-->
    <公司网站>http://www.zte.com.cn/</公司网站>
    <!--这里联系方式出现了2次-->
    <联系方式>地址:深圳市南山区高新技术产业园科技南路中兴通讯大厦</联系方式>
    <联系方式>电话:0755-26770000</联系方式>
    </招聘信息>
    
    <招聘信息>
    <公司名>
    阿里巴巴
    </公司名>
    <!--这里招聘职位出现了1次-->
    <招聘职位>软件测试工程师</招聘职位>
    <!--没有出现公司网站-->
    <!--没有出现联系方式-->
    </招聘信息>
    
    </IT求职>

    3.定义有效的元素属性

    在DTD中定义属性时,我们采用下面的格式:

    <!ATTLIST 元素名 属性名 (属性值 属性类型 缺省值)*>

    例如:

    <!ATTLIST 作者
    
    姓名 CDATA #REQUIRED
    
    性别 (男|女) "男"
    
    联系方式 CDATA #IMPLIED
    
    >

    根据XML文件是否必须为一个属性提供取值,属性的缺省值又可以分为以下四类:

    • 必须赋值的属性REQUIRED
    • 属性值可有可无的属性IMPLIED
    • 固定取值的属性FIXED
    • 自定义的缺省值

    下面用一个例子来说明这四类缺省属性:

    <?xml version="1.0" encoding="gb2312"?>
    
    <!DOCTYPE 图书信息 [
    <!ELEMENT 图书信息 (书名,作者,价格)*>
    <!ELEMENT 书名 (#PCDATA)>
    <!ELEMENT 作者 (#PCDATA)>
    <!ELEMENT 价格 (#PCDATA)>
    <!ATTLIST 作者 
    姓名 CDATA #REQUIRED
    性别 (男|女) "男"
    联系方式 CDATA #IMPLIED
    分类 CDATA #FIXED "WEB编程技术"
    >
    ]>
    
    <图书信息>
    <书名>ASP.NET案例开发集锦</书名>
    <作者 姓名="赵辉、杨丽敏"/>
    <价格>37.00</价格>
    
    <书名>C#高级编程</书名>
    <作者 姓名="wrox" 联系方式="http://www.wrox.com"/>
    <价格>128.00</价格>
    
    <书名>HTML XHTML CSS基础教程(第6版)</书名>
    <作者 姓名="Elizabeth Castro" 分类="WEB编程技术"/>
    <价格>50.00</价格>
    
    <书名>ASP.NET 2.0 应用开发技术</书名>
    <作者 姓名="孟宪会(net_lover)" 性别="男"/>
    <价格>59.00</价格>
    </图书信息>

    上面的例子为子元素"作者"定义了4个属性,分别是"姓名"(#REQUIRED类型)、"联系方式"(#IMPLIED类型)、"分类"(#FIXED类型)、"性别"(自定义类型)。

    在第一本书《ASP.NET案例开发集锦》中,只出现了"姓名",但其实际属性有两项,还有一个是#FIXED类型的"分类"。

    在第二本书《C#高级编程》中,除了必须出现的"姓名",还出现了#IMPLIED类型的"联系方式",算上#FIXED类型的"分类",实际属性有三项。

    在第三本书《HTML XHTML CSS基础教程(第6版》中,除了"姓名",还显式出现了#FIXED类型的"分类",它的实际属性与第一本书相同。

    在第四本书《ASP.NET 2.0 应用开发技术》中,"姓名"后出现了自定义属性"性别",它只有两个值"男"和"女",默认为"男",出现其他值将显示错误。

    属性类型分为以下10种:

    • CDATA
    • Enumerated
    • ID
    • IDREF
    • IDREFS
    • ENTITY
    • ENTITIES
    • NMTOKEN
    • NMTOKENS
    • NOTATION

    CDATA和Enumerated(枚举类型)在上面的例子中已有所说明,主要研究一下其他的属性类型:

    ID属性类型

    每个ID类型的属性必须有不同的值,大多数ID属性使用#REQUIRED,且ID类型和#FIXED不兼容.属性不能既是固定的,又有ID类型.这是因为#FIXED属性只能有一个值。

    看下面的错误示例:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE 职员信息 [
    <!ELEMENT 职员信息 (普通职员)*>
    <!ELEMENT 普通职员 (#PCDATA)>
    <!ATTLIST 普通职员 编号 ID #REQUIRED>
    ]>
    
    <职员信息>
    <普通职员 编号="8">张三</普通职员>
    <普通职员 编号="E8">李四</普通职员>
    <普通职员 编号="E8">王五</普通职员>
    </职员信息>

    上面的文件有2个错误,一个是 编号="8" 这里,ID属性不能是纯数字,必须要以字母或下划线开头;另一个是出现了两个"E8"的编号,这与ID属性的定义是相违背的。

    IDREF属性类型

    具有IDREF类型的属性的值是文档中另一个元素的ID。

    <?xml version="1.0" encoding="gb2312"?>
    
    <!DOCTYPE 武将信息 [
    <!ELEMENT 武将信息 (姓名)*>
    <!ELEMENT 姓名 (#PCDATA)>
    <!ATTLIST 姓名 编号 ID #REQUIRED>
    <!ATTLIST 姓名 君主 IDREF #IMPLIED>
    ]>
    
    <武将信息>
    <姓名 编号="P1">曹操</姓名>
    <姓名 编号="P2">刘备</姓名>
    <姓名 编号="P3">孙权</姓名>
    
    <姓名 编号="P4" 君主="P1">许楮</姓名>
    <姓名 编号="P5" 君主="P2">关羽</姓名>
    <姓名 编号="P6" 君主="P3">甘宁</姓名>
    </武将信息>

    上面的例子中,由于"君主"属性指定为IDREF,所以其内容必须为ID属性的"编号"里的值。

    IDREFS属性类型

    IDREF属性的值只能为一个.但如果要描述一对多的关系,例如三国里所有人都只有一个君主,但却会有多个子女.这时候就要用到IDREFS属性了

    <?xml version="1.0" encoding="gb2312"?>
    
    <!DOCTYPE 武将信息 [
    <!ELEMENT 武将信息 (姓名)*>
    <!ELEMENT 姓名 (#PCDATA)>
    <!ATTLIST 姓名 编号 ID #REQUIRED>
    <!ATTLIST 姓名 子女 IDREFS #IMPLIED>
    ]>
    
    <武将信息>
    <姓名 编号="C1">关平</姓名>
    <姓名 编号="C2">关兴</姓名>
    <姓名 编号="C3">孙策</姓名>
    <姓名 编号="C4">孙权</姓名>
    <姓名 编号="C5">孙尚香</姓名>
    
    <姓名 编号="F1" 子女="C1 C2">关羽</姓名>
    <姓名 编号="F2" 子女="C3 C4 C5">孙坚</姓名>
    </武将信息>

    ENTITY属性类型

    ENTITY类型属性使人们能把外部二进制数据(即外部未解析的普通实体)链接到文档,ENTITY属性的典型例子是一幅图像,该图像由来自与另一个URL的二进制数据组成

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE 图像 [
    <!ELEMENT 图像 EMPTY>
    <!ATTLIST 图像 来源 ENTITY #REQUIRED>
    <!ENTITY Logo SYSTEM "logo.gif">
    ]>
    <图像 来源="&Logo;"/>

    ENTITIES属性类型

    ENTITIES是ENTITY的复数形式.ENTITIES类型的属性值由空格分隔多个未解析的实体名称组成.每个实体名称引用一个外部的非XML数据源.这个方法的一个用途是轮流显示不同图片的幻灯片,如下所示:

    <?xml version="1.0" encoding="gb2312"?>
    
    <!DOCTYPE 幻灯片 [
    <!ELEMENT 幻灯片 EMPTY>
    <!ATTLIST 幻灯片 来源 ENTITY #REQUIRED>
    <!ENTITY PIC1 SYSTEM "picture1.jpg">
    <!ENTITY PIC2 SYSTEM "picture2.gif">
    <!ENTITY PIC3 SYSTEM "picture3.jpg">
    ]>
    
    <幻灯片 来源="&PIC1; &PIC2; &PIC3;"/>

    NMTOKEN属性类型

    NMTOKEN属性类型限制有效的XML名称记号的属性值,除了空格,任何字符都被认为是有效的。

    <?xml version="1.0" encoding="gb2312"?>
    
    <!DOCTYPE 客户资料 [
    <!ELEMENT 客户资料 (联系地址)*>
    <!ELEMENT 联系地址 (#PCDATA)>
    <!ATTLIST 联系地址 城市 NMTOKEN #REQUIRED>
    ]>
    
    <客户资料>
    
    <联系地址 城市="London">张三</联系地址>
    
    <联系地址 城市="010北京">李四</联系地址>
    
    <联系地址 城市="New York">王五</联系地址>
    
    </客户资料>

    上面的例子,"010北京"虽然是以数字开头,但由于是NMTOKEN类型,所以它也是合法的.但最后的"New York"为非法,因为NMTOKEN类型限制了空格的使用。

    NMTOKENS属性类型

    NMTOKENS是NMTOKEN的复数形式,它允许出现一组值,同NMTOKEN的规则一样,不限制符号的使用。它可以出现空格,但空格的作用是分割不同的记号

    <?xml version="1.0" encoding="gb2312"?>
    
    <!DOCTYPE 注册信息 [
    <!ELEMENT 注册信息 (用户资料)*>
    <!ELEMENT 用户资料 (#PCDATA)>
    <!ATTLIST 用户资料 爱好 NMTOKENS #REQUIRED>
    ]>
    
    <注册信息>
    
    <用户资料 爱好="足球 篮球">张三</用户资料>
    
    <用户资料 爱好="唱歌 跳舞">李四</用户资料>
    
    <用户资料 爱好="Play the Piano">王五</用户资料>
    
    </注册信息>

    上面的例子虽然没有错误,但最后的"play the piano"本来想表达的意思是"弹钢琴",但由于NMTOKENS的限制,被拆解成了"play"、"the"、"Piano"三个部分。所以在遇到NMTOKENS类型属性时,要特别注意空格的使用。

    NMTOKENS属性类型

    NOTATION对于使用非XML格式的数据非常有用。现实世界中存在很多无法或不易用XML格式组织的数据,例如图象、声音、影象等等。对于这些数据,XML应用程序常常并不提供直接的应用支持。通过为它们设定NOTATION类型的属性,可以向应用程序指定一个外部的处理程序

    <?xml version="1.0" encoding="gb2312"?>
    
    <!DOCTYPE 文件 [
    <!ELEMENT 文件 (声音文件)>
    <!ELEMENT 声音文件 (#PCDATA)>
    <!NOTATION MP SYSTEM "mplayer32.exe">
    <!NOTATION ST SYSTEM "soundtool">
    <!NOTATION SM SYSTEM "Sound Machine">
    <!ATTLIST 声音文件 处理程序 NOTATION (MP|SM|ST) #REQUIRED>
    ]>
    
    <文件>
    <声音文件 处理程序="MP">Lydia.mp3</声音文件>
    </文件>
  • 相关阅读:
    Ubuntu配置sublime text 3的c编译环境
    ORA-01078错误举例:SID的大写和小写错误
    linux下多进程的文件拷贝与进程相关的一些基础知识
    ASM(四) 利用Method 组件动态注入方法逻辑
    基于Redis的三种分布式爬虫策略
    Go语言并发编程总结
    POJ2406 Power Strings 【KMP】
    nyoj 会场安排问题
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    Java的String、StringBuffer和StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/CoderWayne/p/4484386.html
Copyright © 2011-2022 走看看