Content restriction and attribute validation on the same element in XSD - attributes

I would like to validate that an element 'Test' should
Have its content restricted (for example, using a pattern restriction), and
Contain certain attributes (for example, 'id', 'class' and 'name').
The XSD I'm writing looks like this:
<xsd:element name="Test" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType mixed="true">
<xsd:simpleContent>
<xsd:restriction>
<xsd:pattern value="xyz"/>
</xsd:restriction>
</xsd:simpleContent>
<xsd:attribute name="id" type="xsd:string"></xsd:attribute>
<xsd:attribute name="class" type="xsd:string"></xsd:attribute>
<xsd:attribute name="name" type="xsd:string"></xsd:attribute>
</xsd:complexType>
</xsd:element>
However, when I code this in Visual Studio, I get the following error on the 'xsd:attribute' elements:
'attribute' and content model are mutually exclusive
Is there a way to validate both a content restriction and attributes on the same element?

You need to separate out your restriction and give it a name, then refer to it as a base type for an extension. Like this:
<xsd:simpleType name="RestrictedString">
<xsd:restriction base="xsd:string">
<xsd:pattern value="xyz" />
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="Test">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="RestrictedString">
<xsd:attribute name="id" type="xsd:string" />
<xsd:attribute name="class" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>

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.

Passing pattern value as parameter or reference dynamic

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.

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 can I represent a sequence of an element with coupled attribute types in XSD?

I have the following requirements and am trying to determine how best to model the XSD to represent these requirements.
I have many instances of an XML element, say <box>. Each <box> has a required attribute t="[box-type]" and each box with a specific type, say t="tall" has another required attribute v="10" which represents the height of the tall box. All <box>es have both t and v attributes, but the restriction on what values are accepted for their v attributes depends on the value of their t attribute.
For example, take the following XML:
<box t="tall" v="10"/>
<box t="named" v="George"/>
<box t="colored" v="green"/>
Now, in my XSD I need to be able represent a sequence of such elements. My thought was to do something like the following which just lists out all of the allowed box types in my sequence (at the end of the following snippet):
<xsd:simpleType name="box_types">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="tall" />
<xsd:enumeration value="named" />
<xsd:enumeration value="colored" />
</xsd:restriction>
</xsd:simpleType>
<!--Box base-->
<xsd:complexType name="box_type">
<xsd:attribute name="t" use="required" type="box_types"/>
<xsd:attribute name="v" use="required"/>
</xsd:complexType>
<!--Box concrete types-->
<xsd:complexType name="tall_box_type">
<xsd:complexContent>
<xsd:extension base="box_type">
<xsd:attribute name="t" fixed="tall" use="required"/>
<xsd:attribute name="v" type="xsd:int" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="named_box_type">
<xsd:complexContent>
<xsd:extension base="box_type">
<xsd:attribute name="t" fixed="named" use="required"/>
<xsd:attribute name="v" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="colored_box_type">
<xsd:complexContent>
<xsd:extension base="box_type">
<xsd:attribute name="t" fixed="colored" use="required"/>
<xsd:attribute name="v" type="xsd:token" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<!--And finally, the place where boxes show up-->
<xsd:complexType name="box_usage">
<xsd:sequence>
<xsd:element name="box" type="tall_box_type"/>
<xsd:element name="box" type="named_box_type"/>
<xsd:element name="box" type="colored_box_type"/>
</xsd:sequence>
</xsd:complexType>
Unfortunately, that is not a valid XSD - VS gives me the several errors, the most unfortunate being Elements with the same name and in the same scope must have the same type. Any advice on how I can represent these t/v coupled attribute restrictions in an XSD?
XML Schema 1.0 can't validate dependencies between values. Your options are:
Change your XML. For instance, use tallBox, colorBox and nameBox as element names.
Validate the general structure with XSD and validate values with program logic (or some other tool like Schematron or an XSLT stylesheet).
Use XML Schema 1.1, which can validate value constraints but is not commonly supported, yet.

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