- From: Paul Kiel <paul@hr-xml.org>
- Date: Tue, 16 Apr 2002 14:49:11 -0400 (EDT)
- To: <xmlschema-dev@w3.org>
Thanks Jeni and Mark, You both have hit the crux of the matter exactly. I guess I was hoping for that magical "other option" that would meet our needs and remain simple. I think we are just plain stuck with creating a different Person for each transaction. This won't prevent me from creating a model for reference and consistency, however. One that is seperate from transactional schemas. That "pain" as Mark puts it is worth a bit of effort. The derivation by restriction is not an option, derivation by extension (with external constraints) is a good approach but one that would take some convincing, and using abstract / redefine would be good job security for the schema editors like me but not so for domain experts who are newer to xml schema. Thanks, Paul Kiel ----- Original Message ----- From: "Jeni Tennison" <jeni@jenitennison.com> To: "Paul Kiel" <paul@hr-xml.org> Cc: <xmlschema-dev@w3.org> Sent: Tuesday, April 16, 2002 12:00 PM Subject: Re: Schema Design: Composition vs Subclassing > Hi Paul, > > > I have a question about the effect of this best practice. It is > > regarding context-specific use of components. Let's take the element > > <Person> in a human resources context. (BTW - <Person> is too broad > > a concept to actually encode, this is only for discussion). We may > > want to use a <Person> in many contexts, where some of its > > components are required in one and not in another. Let's say we have > > two transactions of Person below (and that all children are stand > > alone components): > > > > Transaction 1: > > <Person> > > <Name/><!-- required --> > > <Skills/><!-- required --> > > <Height/><!-- required --> > > <Weight/><!-- required --> > > </Person> > > In this transaction, we need all the data about this person to do > > the transaction. > > > > Transaction 2: > > <Person> > > <Name/><!-- required --> > > <Skills/><!-- optional --> > > </Person> > > In this transaction, we only need a name of the person and the > > skills are optional. The Height and Weight have no meaning in this > > context and can't occur. > > None of the methods that you suggested seem particularly good to me. > In the example above, you have one thing that stays the same (<Person> > always has a <Name> element child), and two things that change > (whether <Skills> is required or optional, and whether the <Person> > includes a <Height> and <Weight>). > > If you can take advantage of treating all Person elements in the same > way when it comes to their Name (i.e. that you can get some code reuse > out of it), I'd make a general PersonType that included a <Name> > element: > > <xs:complexType name="PersonType" abstract="yes"> > <xs:sequence> > <xs:element name="Name" type="xs:string" /> > </xs:sequence> > </xs:complexType> > > I'd then create types that extend this base type. For Transaction 1: > > <xs:complexType name="Transaction1PersonType"> > <xs:extension base="PersonType"> > <xs:sequence> > <xs:element name="Skills" type="SkillsType" /> > <xs:element name="Height" type="xs:decimal" /> > <xs:element name="Weight" type="xs:decimal" /> > </xs:sequence> > </xs:extension> > </xs:complexType> > > <xs:complexType name="Transaction2PersonType"> > <xs:extension base="PersonType"> > <xs:sequence> > <xs:element name="Skills" type="SkillsType" minOccurs="0" /> > </xs:sequence> > </xs:extension> > </xs:complexType> > > If you can't take advantage of the fact that the Person elements in > Transaction1 and Transaction2 are similar (i.e. for some reason you > can't share code between them) then you could design through > composition instead. This time the shared components should go into > groups: > > <xs:group name="NameGroup"> > <xs:sequence> > <xs:element name="Name" type="xs:string" /> > </xs:sequence> > </xs:group> > > <xs:group name="SkillsGroup"> > <xs:sequence> > <xs:element name="Skills" type="SkillsType" /> > </xs:sequence> > </xs:group> > > <xs:group name="HeightAndWeightGroup"> > <xs:sequence> > <xs:element name="Height" type="xs:decimal" /> > <xs:element name="Weight" type="xs:decimal" /> > </xs:sequence> > </xs:group> > > Then you could have two (possibly anonymous) types that bring those > groups together as required: > > <xs:complexType name="Transaction1PersonType"> > <xs:sequence> > <xs:group ref="NameGroup" /> > <xs:group ref="SkillsGroup" /> > <xs:group ref="HeightAndWeightGroup" /> > </xs:sequence> > </xs:complexType> > > <xs:complexType name="Transaction2PersonType"> > <xs:sequence> > <xs:group ref="NameGroup" /> > <xs:group ref="SkillsGroup" minOccurs="0" /> > </xs:sequence> > </xs:complexType> > > A third possibility would be to have an abstract version of the > PersonType that includes a group with nothing in it as a placeholder: > > <xs:complexType name="PersonType" abstract="yes"> > <xs:sequence> > <xs:element name="Name" type="xs:string" /> > <xs:group ref="PersonGroup" /> > </xs:sequence> > </xs:complexType> > > <xs:group name="PersonGroup"> > <xs:sequence /> > </xs:group> > > Then, in the schema for Transaction 1, you can redefine the > PersonGroup group to add the required elements: > > <xs:redefine href="baseSchema"> > <xs:group name="PersonGroup"> > <xs:sequence> > <xs:group ref="PersonGroup" /> > <xs:element name="Skills" type="SkillsType" /> > <xs:element name="Height" type="xs:decimal" /> > <xs:element name="Weight" type="xs:decimal" /> > </xs:sequence> > </xs:group> > </xs:redefine> > > and similarly in the schema for Transaction 2: > > <xs:redefine href="baseSchema"> > <xs:group name="PersonGroup"> > <xs:sequence> > <xs:group ref="PersonGroup" /> > <xs:element name="Skills" type="SkillsType" minOccurs="0" /> > </xs:sequence> > </xs:group> > </xs:redefine> > > Personally, I think I'd favour 1, but I'm in the process of being > persuaded towards composition, so I reserve the right to change my > mind. > > Cheers, > > Jeni > > --- > Jeni Tennison > http://www.jenitennison.com/ > > >
Received on Wednesday, 17 April 2002 05:08:20 UTC