[
Lists Home |
Date Index |
Thread Index
]
Thanks George and Michael
As I'm stuck with MSXML at the moment I presume that rules out Schematron
constructs?
I'll have a go using the xsi:type to distinguish types.
Thanks again
Joe
>From: George Cristian Bina <george@oxygenxml.com>
>To: joe@rightway.co.uk
>CC: xml-dev@lists.xml.org
>Subject: Re: [xml-dev] Schema definition of element with optional children
>Date: Tue, 02 May 2006 17:17:37 +0300
>
>Hi Joe,
>
>There are a couple of possibilities. One is to use xsi:type in the instance
>document to specify if you have a deleted or inserted, etc. address. A
>sample schema and instance document look like below
>
><?xml version="1.0" encoding="UTF-8"?>
><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
> elementFormDefault="qualified">
> <xs:element name="address" type="addressType"> </xs:element>
> <xs:complexType name="addressType" abstract="true"/>
> <xs:complexType name="inserted">
> <xs:complexContent>
> <xs:extension base="addressType">
> <xs:sequence>
> <xs:element ref="addressLine1"/>
> <xs:element ref="addressLine2"/>
> <xs:element ref="city"/>
> <xs:element ref="postCode"/>
> <xs:element ref="country"/>
> </xs:sequence>
> </xs:extension>
> </xs:complexContent>
> </xs:complexType>
>
> <xs:complexType name="deleted">
> <xs:complexContent>
> <xs:extension base="addressType"/>
> </xs:complexContent>
> </xs:complexType>
>
> <xs:element name="addressLine1">
> <xs:complexType/>
> </xs:element>
> <xs:element name="addressLine2">
> <xs:complexType/>
> </xs:element>
> <xs:element name="city">
> <xs:complexType/>
> </xs:element>
> <xs:element name="postCode">
> <xs:complexType/>
> </xs:element>
> <xs:element name="country">
> <xs:complexType/>
> </xs:element>
></xs:schema>
>
><address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>xsi:type="inserted">
> <addressLine1/>
> <addressLine2/>
> <city/>
> <postCode/>
> <country/>
></address>
>
><address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>xsi:type="deleted"/>
>
>Another possibility is to declare the address element abstract and make two
>elements, for instance insertedAddress and deletedAddress that can
>substitute address. For that change the
>
><xs:element name="address" type="addressType" abstract="true"/>
>
>from the above schema with:
>
><xs:element name="address" type="addressType" abstract="true"/>
> <xs:element name="insertedAddress" type="inserted"
>substitutionGroup="address"/>
> <xs:element name="deletedAddress" type="deleted"
>substitutionGroup="address"/>
>
>and in that case the sample instances will look like:
>
><insertedAddress>
> <addressLine1/>
> <addressLine2/>
> <city/>
> <postCode/>
> <country/>
></insertedAddress>
>
>
><deletedAddress/>
>
>
>If you want to keep the instance exactly as it is then you can use
>Schematron embedded rules, below there is a sample schema and instances.
>
><?xml version="1.0" encoding="UTF-8"?>
><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
>elementFormDefault="qualified">
> <xs:element name="address">
> <xs:annotation>
> <xs:appinfo>
> <pattern xmlns="http://www.ascc.net/xml/schematron"
>name="testAddress">
> <rule context="address[@recordStatus='deleted']">
> <assert test="count(*)=0">Deleted address should have no
>content.</assert>
> </rule>
> </pattern>
> </xs:appinfo>
> </xs:annotation>
> <xs:complexType>
> <xs:sequence>
> <xs:element ref="addressLine1"/>
> <xs:element ref="addressLine2"/>
> <xs:element ref="city"/>
> <xs:element ref="postCode"/>
> <xs:element ref="country"/>
> </xs:sequence>
> <xs:attribute name="recordStatus" use="required">
> <xs:simpleType>
> <xs:restriction base="xs:NMTOKEN">
> <xs:enumeration value="inserted"/>
> <xs:enumeration value="deleted"/>
> </xs:restriction>
> </xs:simpleType>
> </xs:attribute>
> </xs:complexType>
> </xs:element>
> <xs:element name="addressLine1">
> <xs:complexType/>
> </xs:element>
> <xs:element name="addressLine2">
> <xs:complexType/>
> </xs:element>
> <xs:element name="city">
> <xs:complexType/>
> </xs:element>
> <xs:element name="postCode">
> <xs:complexType/>
> </xs:element>
> <xs:element name="country">
> <xs:complexType/>
> </xs:element>
></xs:schema>
>
>
><address recordStatus="inserted">
> <addressLine1/>
> <addressLine2/>
> <city/>
> <postCode/>
> <country/>
></address>
>
><address recordStatus="deleted"/>
>
>for an invalid instance like:
>
><address recordStatus="deleted">
> <addressLine1/>
> <addressLine2/>
> <city/>
> <postCode/>
> <country/>
></address>
>
>you will get
>
>SystemID: C:\george\workspace\oXygen\samples\test.xml
>Location: 1:0
>Description: Deleted address should have no content. (count(*)=0)
>
>Best Regards,
>George
>---------------------------------------------------------------------
>George Cristian Bina
><oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
>http://www.oxygenxml.com
>
>
>Joe Fawcett wrote:
>>Dear All
>>
>>I'm struggling to find the best way to restrict an element that holds
>>address data.
>>If the address is to be deleted it will look like this:
>><address recordStatus="deleted"/>
>>
>>if it's new or an update it will be along the lines of:
>>
>><address recordStatus="inserted">
>> <addressLine1></addressLine1>
>> <addressLine2></addressLine2>
>> <city></city>
>> <postCode></postCode>
>> <country></country>
>></address>
>>
>>with various fields being optional, these are UK addresses only.
>>
>>What's the most efficient way to declare this using XSD only as I believe
>>I can't say, "if recordStatus = 'deleted' then..." etc?
>>
>>I believe I have to give a choice of two types but this seems tedious?
>>
>>Thanks
>>
>>Joe
>>
>>
>>
>>-----------------------------------------------------------------
>>The xml-dev list is sponsored by XML.org <http://www.xml.org>, an
>>initiative of OASIS <http://www.oasis-open.org>
>>
>>The list archives are at http://lists.xml.org/archives/xml-dev/
>>
>>To subscribe or unsubscribe from this list use the subscription
>>manager: <http://www.oasis-open.org/mlmanage/index.php>
>>
|