DTD中的ENTITY声明是XML文档类型定义里的重要语法,用于定义可复用的实体,能够简化XML文档的编写,减少重复内容的书写。实体可以理解为一段内容的别名,在XML文档中引用实体名称时,解析器会自动将其替换为对应的实体内容。
ENTITY声明的基本分类
ENTITY声明主要分为内部实体和外部实体两类,内部实体的内容直接定义在DTD中,外部实体的内容来自外部的URI资源。两类实体的语法格式存在差异,适用场景也不同。
内部实体的声明与使用
内部实体的声明语法为<!ENTITY 实体名称 "实体内容">,实体名称需要符合XML命名规范,实体内容可以是文本、特殊字符等。声明完成后,在XML文档中通过&实体名称;的格式引用实体。
以下是一个内部实体的使用示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ENTITY author "张三">
<!ENTITY content "这是一段测试内容">
]>
<note>
<to>李四</to>
<from>&author;</from>
<body>&content;</body>
</note>
上述示例中,先声明了author和content两个内部实体,之后在XML元素中引用这两个实体,解析后的文档中<from>元素的内容会变为张三,<body>元素的内容会变为这是一段测试内容。
外部实体的声明与使用
外部实体的内容存储在外部文件中,声明语法为<!ENTITY 实体名称 SYSTEM "外部资源URI">,如果外部资源有公共标识符,还可以使用PUBLIC关键字声明。外部实体同样通过&实体名称;的格式引用。
以下是外部实体的使用示例,假设外部文件test.txt的内容为外部实体测试内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ENTITY external_content SYSTEM "https://ipipp.com/test.txt">
]>
<note>
<body>&external_content;</body>
</note>
解析该XML文档时,解析器会读取https://ipipp.com/test.txt文件的内容,替换到<body>元素中。
ENTITY声明的注意事项
- 实体名称不能以数字或特殊符号开头,只能以字母或下划线开头,且区分大小写。
- 内部实体的内容中如果包含特殊字符,需要进行转义,比如<需要转义为<lt;,>需要转义为<gt;。
- 外部实体的使用需要注意资源的可访问性,如果外部URI无法访问,XML解析会出错。
- 不要在DTD中定义循环引用的实体,否则会导致解析器陷入死循环,引发解析错误。
参数实体的特殊用法
除了普通实体,DTD还支持参数实体,参数实体只能在DTD内部使用,声明语法为<!ENTITY % 实体名称 "实体内容">,引用格式为%实体名称;。参数实体通常用于简化DTD的编写,比如复用DTD中的重复定义片段。
以下是参数实体的使用示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ENTITY % common_attrs "id CDATA #IMPLIED class CDATA #IMPLIED">
<!ELEMENT note (to,from,body)>
<!ATTLIST note %common_attrs;>
<!ELEMENT to (#PCDATA)>
<!ATTLIST to %common_attrs;>
<!ELEMENT from (#PCDATA)>
<!ATTLIST from %common_attrs;>
<!ELEMENT body (#PCDATA)>
<!ATTLIST body %common_attrs;>
]>
<note id="1" class="info">
<to>李四</to>
<from>张三</from>
<body>测试内容</body>
</note>
上述示例中,common_attrs参数实体定义了公共的属性列表,多个元素通过引用该参数实体复用属性定义,减少了DTD的重复代码。