3

I want to enforce my ID/IDRefs with a pattern. The code below works perfectly, but I would like to optimize it a bit, because all the different types are the same except for the first 3 characters in the pattern. Is it possible to have a generic type, which takes the prefix (SEG, ITI, ...) as a parameter ?

<xsd:complexType name="SegmentIDRefs">
    <xsd:complexContent>
        <xsd:restriction base="common:IDRefs">
            <xsd:attribute name="Id">
                <xsd:simpleType>
                    <xsd:restriction base="xsd:ID">
                        <xsd:pattern value="SEG_[\da-fA-F]{8}"/>
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:attribute>
            <xsd:attribute name="GUID" type="common:external.GUID"/>
            <xsd:attribute name="RefId">
                <xsd:simpleType>
                    <xsd:restriction base="xsd:IDREF">
                        <xsd:pattern value="SEG_[\da-fA-F]{8}"/>
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:attribute>
        </xsd:restriction>
    </xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="ItineraryIDRefs">
    <xsd:complexContent>
        <xsd:restriction base="common:IDRefs">
            <xsd:attribute name="Id">
                <xsd:simpleType>
                    <xsd:restriction base="xsd:ID">
                        <xsd:pattern value="ITI_[\da-fA-F]{8}"/>
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:attribute>
            <xsd:attribute name="GUID" type="common:external.GUID"/>
            <xsd:attribute name="RefId">
                <xsd:simpleType>
                    <xsd:restriction base="xsd:IDREF">
                        <xsd:pattern value="ITI_[\da-fA-F]{8}"/>
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:attribute>
        </xsd:restriction>
    </xsd:complexContent>
</xsd:complexType>
dbugger
  • 15,868
  • 9
  • 31
  • 33

1 Answers1

0

Using XSD 1.1 you can use assertions to test the desired regex. This is not really a parametric type as it needs to base the regex on the name of the element.

Example (I've assumed that attributes are compulsory to simplify):

<!-- The ref type contains the attributes and an assertion to test the regex -->
<xsd:complexType name="myRefType">
    <xsd:attribute name="Id" type="xsd:ID" use="required"/>
    <xsd:attribute name="RefId" type="xsd:IDREF" use="required"/>
    <xsd:attribute name="GUID" type="xsd:string"/>

    <!-- Regex prefix is set based on node local name (it can be cahnged to use node first 3 letters if you want) -->
    <xsd:assert test="let $regex:=(
        concat(if (local-name()='itinerary') then 'ITI'
            else if (local-name()='segment') then 'SEG'
            else error(), '_[\da-fA-F]{8}')) 
        return matches(@Id, $regex) and matches(@RefId, $regex)"/>
</xsd:complexType>

<!-- Example root element containing an unbounded number of itinerary and semgent elements-->
<xsd:element name="root">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element name="itinerary" type="common:myRefType" maxOccurs="unbounded"/>
            <xsd:element name="segment" type="common:myRefType" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>

This is not perfect but it is the best solution I was able to find.

sergioFC
  • 5,926
  • 3
  • 40
  • 54