substitutionGroup 是 XSD 中实现元素可替换性的机制,允许全局声明的 substitutable 元素在 XML 实例中替代同名全局 head 元素,要求类型兼容且常配合 abstract、block 等属性控制扩展行为。

substitutionGroup 是 XSD 中实现“元素可替换性”的机制,本质是让一个元素可以合法地替代另一个声明的元素出现在 XML 实例中,常用于构建可扩展、松耦合的 Schema 设计(比如插件式结构、领域特化扩展)。
核心作用:允许用子元素代替父元素位置
它不改变类型继承关系,而是定义“谁能在 XML 文档里顶替谁的位置”。被替换的元素叫 head element(头部元素),用来替换它的叫 substitutable element(可替换元素)。两者必须类型兼容(即 substitutable 元素的类型是 head 元素类型的子类型,或完全相同)。
典型场景:
- 定义一个通用的 <item> 作为占位符;
- 后续扩展出 <book>、<movie> 等具体元素,都声明为可替换 <item>;
- XML 中就能在原本只允许 <item> 的地方,直接写 <book> 或 <movie>。
语法写法:在元素声明中加 substitutionGroup 属性
需满足两个前提:
- head 元素必须是全局声明的(即在 <xs:schema> 直接下定义,不能嵌套在 <xs:complexType> 内);
- substitutable 元素也必须是全局声明的。
示例:
<xs:element name="item" type="xs:string"/> <p><xs:element name="book" type="bookType" substitutionGroup="item"/></p><p><xs:element name="movie" type="movieType" substitutionGroup="item"/></p><p><xs:complexType name="bookType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="isbn" type="xs:string"/> </xs:extension> </xs:simpleContent> </xs:complexType></p><p><xs:complexType name="movieType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="year" type="xs:gYear"/> </xs:extension> </xs:simpleContent> </xs:complexType></p><p><xs:element name="library"> <xs:complexType> <xs:sequence> <xs:element ref="item" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element>
此时以下 XML 是合法的:
<library> <book isbn="978-0-596-52724-1">Effective XML</book> <movie year="2023">Oppenheimer</movie> </library>
关键限制与注意事项
- substitutionGroup 的值必须是另一个全局
<xs:element>的name,不能是类型名或局部元素 - 可替换元素的类型必须能被 head 元素的类型所接受(XSD 1.0 要求是其子类型或相同;XSD 1.1 支持更宽松的“替代一致性”)
- 一个元素只能属于一个 substitutionGroup(不可多继承式替换)
- 如果 head 元素有
abstract="true",它自身就不能直接出现在 XML 中,只能被替换 —— 这是强制多态的常用手法 - 验证器必须支持 substitutionGroup(主流解析器如 Xerces、Saxon、libxml2 都支持)
配合 abstract 和 block 实现精细控制
进阶用法常组合使用:
-
abstract="true":让 head 元素仅作抽象占位,禁止直接实例化 -
block="#all"或block="substitution":放在 head 元素上,可禁止下游元素通过 substitutionGroup 替换它(用于封禁扩展) -
final="#all":放在 substitutable 元素上,防止它再被其他元素替换
例如:<xs:element name="item" abstract="true"/>
这样 XML 中写 <item>xxx</item> 就会报错,强制用户使用 <book> 或 <movie>。









