3.8 定义符号
XML文档只是一个文本文件,它无法处理更复杂的数据类型,比如图片、声音等,因此XML文档将不负责处理这些数据,而是通过定义一个符号来标识这些数据。
定义符号有两种语法格式,分别用于定义普通符号和公共符号。
定义普通符号的语法格式如下:
定义公共符号的语法格式如下:
由于符号用于标识XML文档中的外部数据,因此符号值通常有如下两种形式:
MIME(多用途Internet邮件扩展)类型:一般说来,通用MIME类型的文件总是由相应的程序负责处理。
外部程序所在路径:这种方式直接指定某个外部程序负责处理XML文档中的外部数据。
不管采用哪种方式定义符号,其实质都是一样的:当XML文档中包含某些非文本格式的数据时,可以使用符号标明这些数据应该由何种外部程序负责处理。由此可见,XML解析器本身并不负责处理这些非文本格式的数据,而通常会调用符号所指定的外部程序来对其进行处理。
符号通常有两个用途:
用来定义未解析实体。
作为NOTATION类型的属性的值。
3.8.1 未解析实体
前面介绍实体时提到有一种外部实体,所谓外部实体,就是专门定义一个外部文件来保存实体的值。前面介绍的保存外部实体的值的外部文件都满足如下两个要求:
该外部文件是一个文本文件。
该外部文件是满足XML要求的结构化文档。
如果保存外部实体的值的外部文件不满足上述两个要求,那么XML文档就无法解析该外部文件里的内容,这时只能将该外部实体声明为未解析实体。
对未解析实体而言,XML解析器也无法正常处理外部文件里的内容,因此它也不会处理外部文件里的内容。
学生提问:XML文档里的内容不是应该由XML解析器负责处理吗?如果XML解析器不负责处理,那这些数据岂不就失去作用了?
答:所有的外部实体都用于将外部文件的内容链接到XML文档中。如果外部文件是文本文件,而且是满足XML要求的文档,XML解析器就可以直接解析外部文件的内容,将外部文件的内容插入XML文档中;如果外部文件不满足这两个要求,那XML解析器就无法直接将外部文件的数据插入XML文档中——但这并不意味着XML解析器将放弃这些数据,相反XML解析器会通知合适的外部程序来处理这些数据,这时候就需要借助于符号了,XML解析器将会通知该符号所指定的外部程序来处理这些数据。由此可见,未解析实体需要和符号保持关联。事实上,每个未解析实体都有一个对应的符号。
由于XML解析器不能处理未解析实体所对应的数据,因此XML文档不能像引用普通实体一样直接引用未解析实体,而需要通过ENTITY、ENTITIES类型的属性来调用。
定义未解析实体的语法格式如下:
由上述语法格式可以看出,定义未解析实体只要在<!ENTITY…>定义后增加NDATA和符号名即可。下面的DTD中定义了2个符号和1个未解析实体:
程序清单:codes\03\3.8\notation.dtd
上面的DTD中定义了一个名为movie的实体,该实体对应的外部文件是http://www.crazyit.org/ test.wmv,通过这种方式就可以将外部文件的内容引入XML文档。但XML解析器无法处理该外部文件的内容,因此为该实体关联了一个名为wmv的符号,表明movie实体对应的是video/x-ms-wmv格式的数据,应该由相应的外部程序负责处理。
外部实体对应的数据无法直接“插入”XML文档,通常只能作为ENTITY或者ENTITIES类型属性的属性值。
3.8.2 ENTITY和ENTITIES类型的属性
定义ENTITY或ENTITIES类型的属性与定义其他类型的属性没有太大的区别,只是在XML文档中使用这些属性时,其值只能是未解析实体。
如下DTD中定义了2个符号和4个未解析实体,还定义了一个ENTITY类型的description属性和一个ENTITIES类型的content属性:
程序清单:codes\03\3.8\entity.dtd
假设有一份XML文档包含一个<book…/>元素,该元素的description属性值是一段电影短片,content属性值是多个PDF文档——很明显,不管是电影短片还是PDF文档,这些都不是XML所能处理的,因此只能采用未解析实体。下面的XML文档就可以满足要求:
程序清单:codes\03\3.8\entity.xml
由上述XML文档可以看出,该文档中的description属性值是一个未解析实体,content属性值则是多个未解析实体,它们之间是以空格隔开的。
注意
一旦声明某个属性的类型是ENTITY或ENTITIES,就意味着该属性值只能是一个或多个未解析实体,而不能是已经解析的实体。对于未解析实体而言,不能通过普通实体引用的方式去引用,它们只能作为ENTITY或ENTITIES类型的属性值。
3.8.3 NOTATION类型的属性
NOTATION类型的属性的属性值只能是符号名,而且定义NOTATION类型的属性时必须采用枚举方法列出该属性所支持的值,其语法格式如下:
由上述语法格式可以看出,定义NOTATION类型的属性的语法有点“怪”——定义其他类型的属性时,只需单独的一个属性名即可;而定义NOTATION类型的属性时,除了需要NOTATION类型名之外,还需要一个额外的枚举定义。如下XML文档中包含了一个NOTATION 类型的属性:
程序清单:codes\03\3.8\notation.xml