如何在现有XSD中兼容MathML 2.0和3.0以验证不同版本XML?
解决方案:用单一XSD兼容MathML 2.0和3.0验证
XSD本身没有自动检测版本并适配的原生“智能”功能,但可以通过以下几种方式实现同一XSD对两个版本MathML的验证支持:
1. 扩展现有MathML 2.0 XSD,整合3.0新增内容
直接修改你的现有XSD,将MathML 3.0专属的元素、属性整合到对应的定义中:
- 对于新增元素:在原有元素的内容模型中,用
<xs:choice>或<xs:sequence>(根据实际结构)加入3.0的元素定义。 - 对于属性扩展:使用
<xs:extension>为原有复杂类型添加3.0支持的属性。 - 示例片段(假设扩展MathML根元素):
<!-- 原有MathML 2.0根元素定义 --> <xs:complexType name="MathML2Root"> <xs:sequence> <!-- 2.0原有子元素 --> <xs:element ref="mrow" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <!-- 扩展为兼容3.0的版本 --> <xs:complexType name="MathMLCompatibleRoot"> <xs:complexContent> <xs:extension base="MathML2Root"> <xs:sequence> <!-- 加入3.0专属子元素 --> <xs:element ref="mlabeledtr" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- 加入3.0专属属性 --> <xs:attribute name="display" type="xs:string"/> </xs:extension> </xs:complexContent> </xs:complexType> - 注意:如果MathML 3.0使用了独立的命名空间,需在XSD中声明该命名空间并正确引用对应的元素/属性。
2. 使用XSD 1.1的条件类型赋值(CTA)
如果你的验证器支持XSD 1.1(如Saxon、Xerces2),可以利用条件类型赋值根据XML中的特征(如命名空间、版本属性、专属元素存在性)动态选择对应的类型定义:
- 示例:根据MathML元素的命名空间选择验证规则
<xs:complexType name="MathContainer"> <!-- 匹配MathML 2.0命名空间的元素 --> <xs:alternative test="namespace-uri(.) = 'http://www.w3.org/1998/Math/MathML'" type="MathML2Type"/> <!-- 匹配MathML 3.0命名空间的元素 --> <xs:alternative test="namespace-uri(.) = 'http://www.w3.org/2000/Math/MathML'" type="MathML3Type"/> <!-- 默认 fallback(可选) --> <xs:alternative type="xs:anyType"/> </xs:complexType> - 若XML未使用不同命名空间,可通过检测3.0专属元素的存在来判断:
<xs:alternative test="exists(./mlabeledtr)" type="MathML3Type"/> <xs:alternative type="MathML2Type"/>
3. 导入双版本XSD并使用宽松内容模型
将官方的MathML 2.0和3.0 XSD都导入到你的主XSD中,然后在需要兼容的位置使用<xs:choice>允许两种版本的元素:
- 示例:
<xs:import namespace="http://www.w3.org/1998/Math/MathML" schemaLocation="mathml2.xsd"/> <xs:import namespace="http://www.w3.org/2000/Math/MathML" schemaLocation="mathml3.xsd"/> <xs:element name="content"> <xs:complexType> <xs:choice> <xs:element ref="mathml2:math"/> <xs:element ref="mathml3:math"/> </xs:choice> </xs:complexType> </xs:element> - 注意:若存在同名但结构不同的元素,必须通过命名空间区分,避免验证冲突。
关键注意事项
- 优先使用命名空间区分版本:这是最清晰的方式,能避免元素名冲突导致的验证问题。
- 测试覆盖两种场景:分别用你的MathML 2.0和3.0测试XML验证,确保规则生效。
- 避免过度宽松的
<xs:any>:除非必要,不要用<xs:any processContents="skip"/>,否则会失去对MathML结构的严格验证。
内容的提问来源于stack exchange,提问作者GreatPretender
相关产品推荐
相关产品推荐

