• 给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</声音文件>
    </文件>
  • 相关阅读:
    Fedora 12/Debian 以root登录图形界面
    贡献一个简单的日志类
    "没有 pthread_create 的手册页条目"解决办法
    OpenBSD 下架设vsftpd
    NetSnmp初步(一):让我们的程序提供snmp服务
    linux socket接收、发送小工具(支持tcp、udp包(组播)的发送接收)
    NetSnmp初步(二):发送Notification
    netbeans添加现有源文件时自动更新Makefile依赖关系
    Fedora Core12的防火墙会过滤掉部分IP数据包,在开发调试时建议关闭防火墙
    NetSnmp初步(三):接收控制命令:实现SNMP的SET命令
  • 原文地址:https://www.cnblogs.com/CoderWayne/p/4484386.html
Copyright © 2020-2023  润新知