Passing pattern value as parameter or reference dynamic - xsd

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>

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.

Related

Is there a way to handle/ignore inline xsd in received xml file in biztalk?

Client sends a file containing customer data in xml. The problem is that it also contains the xsd they use. Is there a way when setting up the source schema in biztalk to make it validate while ignoring the xsd?
I've tried including nodes for it, but it does not validate due to some namespace error, and it keeps looking for the first element node containing customer data
<Root>
<xsd:schema id="Root" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="Root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="Data" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="number" type="xsd:int"/>
<xsd:element name="name">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="60"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="address">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="30"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="Zip">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="5"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="telephone">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="60"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="custNumber">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="11"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="branchnumber" type="xsd:int"/>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:choice>
<xsd:anyAttribute namespace="http://www.w3.org/XML/1998/namespace" processContents="lax"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<Data>
<number>12345</number>
<name>Scrooge McDuck</name>
<address>Address 1</adresse>
<Zip>0000</Zip>
<telephone>1234563290</telephone>
<custNumber>123324</custNumber>
<branchnumber>0</branchnumber>
</Data>
<Data>
<number>23456</number>
<name>Donald Duck</name>
<address>Address 4</adresse>
<Zip>4625</Zip>
<telephone>1234567890</telephone>
<custNumber>123321</custNumber>
<branchnumber>0</branchnumber>
</Data>
</Root>
I don't think this would actually cause a problem.
First, don't bother validating at runtime, no one ever does this and it's never mattered.
The schema should only contain the content nodes, this will work just fine in the Mapper, Properties etc.
Since you're not validating, provided the Schema is valid xml, it'll just go along for the ride and will be ignored.
To Validate in VS, just take the Schema nodes out.

Adding restriction(enumeration) on type with attribute

im having problems with restricting type with attribute. It looks like this(i can't change it).
<xsd:complexType name="TypeWithAttr" abstract="true">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="type" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
I need it to restriction so that it can only take 2 values. I have tried doing it like that
<xsd:complexType name="TypeWithAttrRestriction">
<xsd:complexContent>
<xsd:restriction base="TypeWithAttr">
<xsd:enumeration value="Green"/>
<xsd:enumeration value="Blue"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
But it says that i can't have enumeration under restriction.
If you need to restrict the content that contains a text-only, you should use : simpleContent instead of complexContent.
some thing like this should work:
<xsd:complexType name="TypeWithAttrRestriction">
<xsd:simpleContent>
<xsd:restriction base="TypeWithAttr">
<xsd:enumeration value="Green"/>
<xsd:enumeration value="Blue"/>
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>

How to include an enumeration in complexType?

Kindly let me know if this is the correct way of including enumeration:
How do i restrict the error type to A, E, I and W
<xsd:complexType name="Errors">
<xsd:sequence>
<xsd:element name="Error" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ErrorType">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="1"/>
<xsd:minLength value="1"/>
<xsd:enumeration value="E"/>
<xsd:enumeration value="A"/>
<xsd:enumeration value="W"/>
<xsd:enumeration value="I"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ErrorMsgTxt">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="4000"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

is there a way to link equal type definitions together?

example code:
<xsd:element name="a">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:pattern value="|(([1-9]|[12][0-9]|3[01])/([0-9]|1[12])/[0-9]{1,4})"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="b">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:pattern value="|(([1-9]|[12][0-9]|3[01])/([0-9]|1[12])/[0-9]{1,4})"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
Now the type definition of element a and b are the same. is there a way to "link" those types together so that i do not have to repeat the typing?
Ok, I see. The easiest way to go is to create a named type:
<xsd:simpleType name="PatternType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="|(([1-9]|[12][0-9]|3[01])/([0-9]|1[12])/[0-9]{1,4})" />
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="a" type="tns:PatternType" />
<xsd:element name="b" type="tns:PatternType" />
where tns is a prefix for your schema target namespace

In XSD, how can I define two different elements with the same name?

I have a problem making an xsd file. I need to have an xsd file for xml documents which will look like this:
<message type="login">
<login nick="Ben" gameId="chess" desiredRole="simple "/>
</message>
or like this
<message type="error">
Error message
</message>
Meaning there is always a message tag but it has different attribute type values and depending on type value there are different things inside the message tag. I tried something like this:
<xsd:element name ='message' type='messageType'>
</xsd:element>
<xsd:complexType name='messageType'/>
<xsd:complexType name='error'>
<xsd:complexContent>
<xsd:extension base='messageType'>
<xsd:attribute name ='type' use='required'>
<xsd:simpleType>
<xsd:restriction base='xsd:string'>
<xsd:enumeration value='error'/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name='login'>
<xsd:complexContent>
<xsd:extension base='messageType'>
<xsd:sequence>
<xsd:element name='login'>
<xsd:complexType>
<xsd:attribute name='nick' type='xsd:string' use='required'>
</xsd:attribute>
<xsd:attribute name='gameId' type='xsd:string' use='required'>
</xsd:attribute>
<xsd:attribute name='desiredRole' type='xsd:string' use='required'>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name ='type' use='required'>
<xsd:simpleType>
<xsd:restriction base='xsd:string'>
<xsd:enumeration value='login'/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
but it doesn’t work (I get an error that the attribute type was not defined). Can some one please help me with this?
How about
<message>
<login />
</message>
and
<message>
<error />
</message>
That is, leave off the type attribute, and always have an element inside of message.
XSD doesn't allow you to do precisely what you want to do, which is create an element that has different structures depending on attribute values. However, if you truly need this element to have different structures like this, you can create an element definition that allows all possible structures. You just cannot have it automatically validated by the parser to prove that it conforms to either one definition or the other, exclusively. Not within XSD at any rate.
Try something like this:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="message" type="messageType"/>
<xsd:simpleType name="typeType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="login"/>
<xsd:enumeration value="error"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="login">
<xsd:complexType>
<xsd:attribute name='nick' type='xsd:string' use='required'/>
<xsd:attribute name='gameId' type='xsd:string' use='required'/>
<xsd:attribute name='desiredRole' type='xsd:string' use='required'/>
</xsd:complexType>
</xsd:element>
<xsd:complexType name='messageType'/>
<xsd:sequence>
<xsd:element ref="login" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="type" type="typeType" use="required"/>
</xsd:complexType>
</xsd:schema>

Resources