如何在XSD中定义含特定约束的多子类型元素类型?
Got it, let's solve this XSD requirement where you need IdentifiersType to:
- Contain at least one
Identifierelement whose nestedIDTypeis exactlyPARTY_ID - Allow any additional
Identifierelements, where theirIDTypebelongs to your predefined enumeration (which already includesPARTY_ID, so multiplePARTY_IDentries are allowed)
We'll cover two approaches depending on whether you're using XSD 1.1 (preferred for flexibility) or XSD 1.0 (more limited but compatible with older tools).
Approach 1: XSD 1.1 (Using Assertions)
XSD 1.1 adds support for xsd:assert, which lets you write direct logical constraints on your type. This is the cleanest solution because it doesn't restrict the order of Identifier elements.
Here's the modified XSD fragment:
<xsd:complexType name="IdentifiersType"> <xsd:sequence> <xsd:element name="Identifier" type="cmn:IdentifierType" maxOccurs="unbounded"/> </xsd:sequence> <!-- Assertion to ensure at least one Identifier has IDType = "PARTY_ID" --> <xsd:assert test="count(Identifier[cmn:IDType = 'PARTY_ID']) >= 1"/> </xsd:complexType> <xsd:complexType name="IdentifierType"> <xsd:sequence> <xsd:element name="SourceSystem" type="xsd:string"/> <!-- Added type for completeness --> <xsd:element ref="cmn:IDType"/> <xsd:element name="IDValue" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:simpleType name="IDType"> <xsd:restriction base="xsd:string"> <xsd:minLength value="1"/> <xsd:enumeration value="VENDOR_ID"/> <xsd:enumeration value="VENDOR_SITE_ID"/> <xsd:enumeration value="VENDOR_SITE_NUMBER"/> <xsd:enumeration value="APPLICANT_ID"/> <xsd:enumeration value="AGMNT_ID"/> <xsd:enumeration value="SAMPLE_ID"/> <xsd:enumeration value="PROGRAM_ID"/> <xsd:enumeration value="QUOTE_ID"/> <xsd:enumeration value="AAA_PARTY_ID"/> <xsd:enumeration value="PARTY_ID"/> <!-- Add other enumeration values as needed --> </xsd:restriction> </xsd:simpleType>
Key Notes:
- The
xsd:assertchecks that there's at least oneIdentifierwhere theIDTypechild equalsPARTY_ID. - Your existing
IDTypeenumeration already enforces that allIDTypevalues (including the mandatory one) are valid, so no extra changes are needed for the optional elements. - This approach allows
Identifierelements to be in any order (e.g., you can have a non-PARTY_ID entry first, followed by a PARTY_ID entry).
Approach 2: XSD 1.0 (Workaround Without Assertions)
XSD 1.0 doesn't support assertions, so we need to use type restrictions and sequence ordering to enforce the constraint. This solution has a limitation: it requires all mandatory PARTY_ID identifiers to appear before any optional identifiers.
First, define a subtype of IdentifierType that fixes IDType to PARTY_ID:
<xsd:complexType name="FixedPartyIdIdentifierType"> <xsd:complexContent> <xsd:extension base="cmn:IdentifierType"> <xsd:sequence> <xsd:element name="SourceSystem" type="xsd:string"/> <!-- Override IDType to fix its value --> <xsd:element name="IDType" type="xsd:string" fixed="PARTY_ID"/> <xsd:element name="IDValue" type="xsd:string"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType>
Then update IdentifiersType to require at least one FixedPartyIdIdentifierType followed by any number of the original IdentifierType:
<xsd:complexType name="IdentifiersType"> <xsd:sequence> <!-- At least one Identifier with IDType = PARTY_ID --> <xsd:element name="Identifier" type="cmn:FixedPartyIdIdentifierType" minOccurs="1" maxOccurs="unbounded"/> <!-- Optional Identifiers with IDType from the enumeration --> <xsd:element name="Identifier" type="cmn:IdentifierType" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType>
Key Notes:
- This enforces the mandatory
PARTY_IDrequirement, but restricts the order of elements (all PARTY_ID entries must come first). - The original
IDTypeenumeration still ensures optional identifiers use valid values.
Final Recommendation
If your tooling supports XSD 1.1 (e.g., Saxon, Xerces 2.11+), use the assertion approach—it's simpler and more flexible. If you're stuck with XSD 1.0, the subtype/sequence workaround will work but with the order limitation.
内容的提问来源于stack exchange,提问作者TomAxway

