You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据同元素中兄弟属性值设置XSD属性类型

根据属性值动态约束另一属性的XSD类型

这个需求确实挺常见的——根据同一元素里另一个属性的值,来约束当前属性的类型对吧?不过得先说明:XSD 1.0本身不支持这种条件式的类型关联,所以得用些变通方案;而XSD 1.1提供了原生支持,实现起来会更顺畅。下面分别给你两种场景的具体实现方式:

一、XSD 1.0解决方案(适配旧版解析器)

如果你的项目还在使用只支持XSD 1.0的旧版解析器,咱们得用「联合类型+额外验证」的组合方案:

1. 定义覆盖所有格式的联合类型

先创建一个包含所有允许格式的联合类型,确保ProductCode至少符合其中一种格式要求:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Products">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Product" maxOccurs="unbounded">
          <xs:complexType>
            <xs:attribute name="ProductCodeType" use="required">
              <xs:simpleType>
                <xs:restriction base="xs:string">
                  <xs:enumeration value="Default"/>
                  <xs:enumeration value="Manufacturer"/>
                  <xs:enumeration value="Supplier"/>
                </xs:restriction>
              </xs:simpleType>
            </xs:attribute>
            <xs:attribute name="ProductCode" use="required">
              <xs:simpleType>
                <xs:union memberTypes="DefaultCodeType ManufacturerCodeType SupplierCodeType"/>
              </xs:simpleType>
            </xs:attribute>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <!-- 定义每种类型的具体格式约束 -->
  <xs:simpleType name="DefaultCodeType">
    <xs:restriction base="xs:integer">
      <!-- 这里假设Default类型是3-7位数字,你可以根据实际需求调整 -->
      <xs:minInclusive value="100"/>
      <xs:maxInclusive value="9999999"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="ManufacturerCodeType">
    <xs:restriction base="xs:string">
      <!-- 假设Manufacturer类型是13位数字(比如EAN-13编码) -->
      <xs:pattern value="[0-9]{13}"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="SupplierCodeType">
    <xs:restriction base="xs:string">
      <!-- 假设Supplier类型是字母开头,后跟任意数字 -->
      <xs:pattern value="[A-Za-z][0-9]+"/>
    </xs:restriction>
  </xs:simpleType>
</xsd>

2. 补充条件校验(用Schematron)

上面的XSD只能保证ProductCode格式合法,但没法确保它和ProductCodeType对应。这时候可以用Schematron来添加条件规则,补上这个关联约束:

<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
  <sch:pattern name="ProductCode必须匹配对应的ProductCodeType">
    <sch:rule context="Product[@ProductCodeType='Default']">
      <sch:assert test="matches(@ProductCode, '^[0-9]{3,7}$')">
        Default类型的ProductCode必须是3-7位数字哦!
      </sch:assert>
    </sch:rule>
    <sch:rule context="Product[@ProductCodeType='Manufacturer']">
      <sch:assert test="matches(@ProductCode, '^[0-9]{13}$')">
        Manufacturer类型的ProductCode必须是13位数字哦!
      </sch:assert>
    </sch:rule>
    <sch:rule context="Product[@ProductCodeType='Supplier']">
      <sch:assert test="matches(@ProductCode, '^[A-Za-z][0-9]+$')">
        Supplier类型的ProductCode必须以字母开头后跟数字哦!
      </sch:assert>
    </sch:rule>
  </sch:pattern>
</sch:schema>

二、XSD 1.1解决方案(原生支持条件约束)

如果你的解析器支持XSD 1.1(比如Saxon、Xerces2等),那直接用原生的条件类型分配或者断言就行,不用绕弯子:

方式1:条件类型分配(推荐)

直接根据ProductCodeType的取值,为ProductCode指定对应的类型,逻辑清晰又直观:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1">
  <xs:element name="Products">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Product" maxOccurs="unbounded">
          <xs:complexType>
            <xs:attribute name="ProductCodeType" use="required">
              <xs:simpleType>
                <xs:restriction base="xs:string">
                  <xs:enumeration value="Default"/>
                  <xs:enumeration value="Manufacturer"/>
                  <xs:enumeration value="Supplier"/>
                </xs:restriction>
              </xs:simpleType>
            </xs:attribute>
            <!-- 核心:根据ProductCodeType的值动态选择类型 -->
            <xs:attribute name="ProductCode" use="required">
              <xs:simpleType>
                <xs:alternative test="@ProductCodeType='Default'" type="DefaultCodeType"/>
                <xs:alternative test="@ProductCodeType='Manufacturer'" type="ManufacturerCodeType"/>
                <xs:alternative test="@ProductCodeType='Supplier'" type="SupplierCodeType"/>
              </xs:simpleType>
            </xs:attribute>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <!-- 复用之前定义的各类型约束 -->
  <xs:simpleType name="DefaultCodeType">
    <xs:restriction base="xs:integer">
      <xs:minInclusive value="100"/>
      <xs:maxInclusive value="9999999"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="ManufacturerCodeType">
    <xs:restriction base="xs:string">
      <xs:pattern value="[0-9]{13}"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="SupplierCodeType">
    <xs:restriction base="xs:string">
      <xs:pattern value="[A-Za-z][0-9]+"/>
    </xs:restriction>
  </xs:simpleType>
</xsd>

方式2:使用断言(灵活度更高)

如果需要更复杂的校验逻辑,也可以在Product元素的complexType里添加断言,直接校验属性值的关联关系:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1">
  <xs:element name="Products">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Product" maxOccurs="unbounded">
          <xs:complexType>
            <xs:attribute name="ProductCodeType" use="required">
              <xs:simpleType>
                <xs:restriction base="xs:string">
                  <xs:enumeration value="Default"/>
                  <xs:enumeration value="Manufacturer"/>
                  <xs:enumeration value="Supplier"/>
                </xs:restriction>
              </xs:simpleType>
            </xs:attribute>
            <xs:attribute name="ProductCode" use="required" type="xs:string"/>
            <!-- 添加断言规则,直接关联两个属性 -->
            <xs:assert test="
              (@ProductCodeType='Default' and matches(@ProductCode, '^[0-9]{3,7}$')) or
              (@ProductCodeType='Manufacturer' and matches(@ProductCode, '^[0-9]{13}$')) or
              (@ProductCodeType='Supplier' and matches(@ProductCode, '^[A-Za-z][0-9]+$'))
            ">
              ProductCode的格式必须和对应的ProductCodeType匹配哦!
            </xs:assert>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xsd>

总结一下

  • 要是能用XSD 1.1,优先选条件类型分配,逻辑清晰且是原生支持;
  • 只能用XSD 1.0的话,就用「联合类型+Schematron」的组合,先保证格式合法,再补上关联约束。

内容的提问来源于stack exchange,提问作者dies_felices

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:51:44