XML.orgXML.org
FOCUS AREAS |XML-DEV |XML.org DAILY NEWSLINK |REGISTRY |RESOURCES |ABOUT
OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index]
Re: [xml-dev] Best Practice: constrain an element's content by (1)a run-time selection of alternate types or (2) a run-time selection of childelements using an XPath expression?

Costello, Roger L. a écrit :
>     <Publication kind="book">
>         <Title>Everything is Miscellaneous</Title>
>         <Author>David Weinberger</Author>
>         <Date>2007</Date>
>         <ISBN>0-8050-8811-3</ISBN>
>         <Publisher>Henry Holt and Company, LLC</Publisher>
>     </Publication>
> 
>     <Publication kind="magazine">
>         <Title>Science News</Title>
>         <Date>2005</Date>
>     </Publication>
> 
> PROBLEM STATEMENT
> 
> What is best practice for constraining the content of Publication?

Hi,

This was the topic of my talk at Balisage last year:
http://www.balisage.net/Proceedings/html/2008/Poulard01/Balisage2008-Poulard01.html
Slides:
http://hal.inria.fr/docs/00/32/26/61/ANNEX/Bal2008poul061003.pdf

> APPROACH #1: ALTERNATE TYPES
> Create a BookType and a MagazineType and then select one of them to be Publication's type depending on @kind:
> 
>    if @kind = 'book' then select BookType
>    else select MagazineType
> 
> Here's how it is expressed in XML Schema 1.1:
> 
>    <xs:element name="Publication" type="PublicationType">
>       <xs:alternative test="@kind eq 'magazine'" type="MagazineType" />
>       <xs:alternative test="@kind eq 'book'" type="BookType" />
>    </xs:element>
> 
> 
> You see the (new) <alternative> element being used to select a type for Publication based on the value of @kind. 

When designing declarative markup languages, one often try to put in a 
single vocabulary things that are specialized whereas one can 
generalized some of them: <xs:alternative> is roughly an if-then-else or 
a switch-case statement, but specialized for a specific purpose and 
appliable to select a type (more or less). If we need another context 
where an alternative is needed, we will need to once again upgrade the 
language and invent a new <xs:alternative2> element and next a new 
<xs:alt> element (this time with a variation of the name) and so on.
A single one is sufficient.

Moreover, it doesn't have to belong to that vocabulary: imagine you have 
to patch XHTML with markup languages for making maths or graphics, would 
you design markups in the XHTML namespace ? Not at all, just pick MathML 
and SVG. Why would it be different for markup languages designed for 
processing purpose such as schema (among others) ?
What is missing in the XML landscape is a kind of glue that allows 
different XML vocabularies to cooperate, even when they are declarative 
languages and imperative languages, in the same way that JSP/JSTL/taglib 
  are working, except that they are tightly coupled to Java, work only 
within a Web server, and are not so much declarative.

My own efforts in that way is called Active Tags, and I have designed in 
this framework an experimental schema language called the Active Schema 
Language (ASL) that works like this. You can download the engine and try 
it with the following examples:
http://reflex.gforge.inria.fr/tutorial-schemas.html
The draft of the spec:
http://ns.inria.fr/active-tags/active-schema/active-schema.html

With ASL, I would express the constraints exactly as mentionned:
<asl:element name="Publication">
     <asl:attribute name="kind">
         <xsl:text value="magazine"/>
         <xsl:text value="book"/>
     </asl:attribute>
     <asl:sequence>
         <asl:element ref-elem="Title"/>
         <xsl:if test="{asl:element()/@kind='book'}">
             <xsl:then>
                 <asl:element ref-elem="Author"/>
                 <asl:element ref-elem="Date"/>
                 <asl:element ref-elem="ISBN"/>
                 <asl:element ref-elem="Publisher"/>
             </xsl:then>
             <xsl:else>
                 <asl:element ref-elem="Date"/>
             </xsl:else>
         </xsl:if>
     </asl:sequence>
</asl:element>

You should notice that <xcl:if> is borrowed from another namespace (not 
shown here for brevity), and you can inject foreign elements in several 
places as long as it makes sense in your schema; for example, if the set 
of allowed values of an attribute were available in a database, just 
loop on the resultset of an SQL or XQuery query and define text values 
(<asl:text>) with each of them.
That way, the abstract tree of the schema is no longer static but 
becomes dynamic: the schema can adapt itself to the data to validate 
(switching content models) or whatever relevant in your constraints 
(picking values from a database). That increases dramatically the 
expressiveness of the language.

> APPROACH #2: XPATH EXPRESSION
> 
> Here's how it is expressed in XML Schema 1.1:
> 
> <xs:element name="Publication">
>     <xs:complexType>
>        <xs:sequence>
>             <xs:element name="Title" type="xs:string"  minOccurs="0"/>
>             <xs:element name="Author" type="xs:string" minOccurs="0"
>                                                        maxOccurs="unbounded"/>
>             <xs:element name="Date" type="xs:gYear"  minOccurs="0"/>
>             <xs:element name="ISBN" type="xs:string"  minOccurs="0"/>
>             <xs:element name="Publisher" type="xs:string"  minOccurs="0"/>
>        </xs:sequence>
>        <xs:attribute name="kind" type="xs:string" />
>        <xs:assert test="if (@kind eq 'book') then
>                           Title and Date and ISBN and Publisher and 
>                           empty(* except (Title[1],Date[1],Author,ISBN[1],Publisher[1]))
>                         else
>                             if (@kind eq 'magazine') then
>                                Title and Date and empty(* except (Title[1],Date[1]))
>                             else
>                                Title and Date and 
>                                   empty(* except (Title[1],Date[1], Author))" />
>     </xs:complexType>
> </xs:element>

I wonder how <xs:assert> can be implemented in a way that an XML editor 
would propose the right element at the right moment; suppose the user 
ask for the available elements after the <Title> of a magazine; would 
the editor propose to the user an <Author>, but once selected the 
assertion would say him he has an error ? Or the editor would try to 
insert each candidate element and then apply the assertion in order to 
prune those rejected from the candidate list ?

> WHICH IS BEST PRACTICE?
> 
> Which approach is best practice? 

IMHO, <xs:assert> is certainly useful in some cases, but should be 
avoided as possible: this method let you apply a 2 phase constraint, the 
former with the content model, the latter with the assertion, each 
ignoring the other. Conversely, it is much more clean and efficient to 
build content models dynamically: an editor would propose only the 
elements that are really available in that context. With ASL, the 
candidate elements available after the <Title> of a magazine are only a 
single <Date> element.

-- 
Cordialement,

               ///
              (. .)
  --------ooO--(_)--Ooo--------
|      Philippe Poulard       |
  -----------------------------
  http://reflex.gforge.inria.fr/
        Have the RefleX !


[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index]


News | XML in Industry | Calendar | XML Registry
Marketplace | Resources | MyXML.org | Sponsors | Privacy Statement

Copyright 1993-2007 XML.org. This site is hosted by OASIS