Basic Schema subdivision question.

G

Grant Robertson

I am only just learning about schema basics. I am trying to understand
some fundamental principles about what can be specified within a schema.

If I define an enumerated list of values for an attribute in the root
element, is it then possible to limit which child elements may appear
depending on the value of that attribute? This enumerated attribute would
be used to specify a sub-type for this particular instance of a document.

For instance, if my document sub-type is "Table of Contents" then the
document may only contain designated "Table of Contents" type elements.
However, if the document sub-type is specified as "Index" then the only
type of elements that may appear are those associated with the "Index"
document sub-type. Basically, I want to have different sub-types of
documents that can only contain specific types of information but all
within the same root level doctype and schema.

I guess I could always accomplish this by simply specifying a limited set
of first level child elements specifying that only one of them may
appear. But I think I want to do this by using an attribute of the root
element instead.

I know I could also accomplish this by simply creating independent
schemas, each with their own independent doctype and possible elements.
However, I want to keep all of this within one schema.

Thanks for any assistance.
 
G

George Bina

Hello Grant,

Neither XML Schemas nor DTDs are limited to specifying a single element
that can be the root of a document. So you can define multiple global
elements in one schema and use any of them as the root element.
What you want is known co-occurrence constraint and is not supported by
XML Schema. However, there is a special attribute xsi:type (where xsi
points to the schema instance namespace:
http://www.w3.org/2001/XMLSchema-instance) that can be used to specify
inside the instance document the type of an element, that is you can
specify the type dynamically. So if you want to keep your initial idea
by all means this is the only possible solution: define the type of the
root element and then a couple of typed derived from that type than in
the instance specify the actua; type that you want to use for the root
element using xsi:type.

Best Regards,
George
 
G

Grant Robertson

So if you want to keep your initial idea
by all means this is the only possible solution: define the type of the
root element and then a couple of typed derived from that type than in
the instance specify the actua; type that you want to use for the root
element using xsi:type.


Thank you.
 
G

Grant Robertson

George, it took me a while to process all of this. I've been working on
my system and getting ready for the first day of the semester tomorrow.

Neither XML Schemas nor DTDs are limited to specifying a single element
that can be the root of a document. So you can define multiple global
elements in one schema and use any of them as the root element.

So, would I be correct in saying that all I need to do is list my 5
possible top elements and specify that only one can occur? I don't know
how that is done yet but I know it can be done for other elements within
a schema. Would I do it just the same as anywhere else?

What you want is known co-occurrence constraint and is not supported by
XML Schema. However, there is a special attribute xsi:type (where xsi
points to the schema instance namespace:
http://www.w3.org/2001/XMLSchema-instance) that can be used to specify
inside the instance document the type of an element, that is you can
specify the type dynamically.

This almost makes it sound as if you are saying that I can't do what you
just said I can do. Or are you saying that I can't do it the way I
originally thought of but can do it the way I just mentioned above? When
I went to the web site you listed I got a very terse page that simply
said you can't put attributes in "this namespace." But I didn't know
which namespace they were talking about.

So if you want to keep your initial idea
by all means this is the only possible solution: define the type of the
root element and then a couple of typed derived from that type than in
the instance specify the actua; type that you want to use for the root
element using xsi:type.

Now you have totally lost me. I think I might have confused you by using
the word "type" to refer to what I realize now is best called a "role."
All of my documents will be in the same namespace but I want some of them
to be used for different things. Each of these different uses would be a
different "role."

Or it could be that you are proposing a really elaborate trick to get a
parser to do what I want. I would like to avoid elaborate tricks because
they tend to break when standards get "cleaned up" at a later date.

Sorry for asking so many questions which are probably answered in most
books about XML Schemas. Can you believe there is not a single book on
the topic in this whole town. I am still waiting for the books I ordered
to arrive. Then I'll be cooking with gas.

P.S. I am going to give <oXygen/> a try tomorrow. I'm thinking for $300
difference in price for the academic versions, I can at least give it a
try.
 
G

George Bina

Hello Grant,

You can find below a couple of simple examples.
Suppose you have a schema that defines two global elements toc and
index, each containing toc1, toc2, tocn and, respectively, index1,
index2, indexn:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="toc">
<xs:complexType>
<xs:sequence>
<xs:element name="toc1"/>
<xs:element name="toc2"/>
<xs:element name="tocn"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="index">
<xs:complexType>
<xs:sequence>
<xs:element name="index1"/>
<xs:element name="index2"/>
<xs:element name="indexn"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

Then both instance documents below will be valid against this schema:
<?xml version="1.0" encoding="UTF-8"?>
<toc>
<toc1></toc1>
<toc2></toc2>
<tocn></tocn>
</toc>

and

<?xml version="1.0" encoding="UTF-8"?>
<index>
<index1/>
<index2/>
<indexn/>
</index>

A namespace is just a string. The schema instance namespace is
http://www.w3.org/2001/XMLSchema-instance and it is used to qualify
some attributes with special meaning for XML Schema like
noNamespaceSchemaLocation, schemaLocation, type, nil. Now suppose you
want the same root element, let's say someRoot and its content should
be either toc1, toc2, tocn or index1, index2, indexn depending on an
attribute value. The only possiblity with XML schema is to use xsi:type
as the attribute, thus specifying the type of the someRoot root
element.

For instance you can have the following instance documents:

<?xml version="1.0" encoding="UTF-8"?>
<someRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="tocType">
<toc1></toc1>
<toc2></toc2>
<tocn></tocn>
</someRoot>

and

<?xml version="1.0" encoding="UTF-8"?>
<someRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="indexType">
<index1/>
<index2/>
<indexn/>
</someRoot>

that will be valid against the following schema
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="someRoot" type="xs:anyType"/>
<xs:complexType name="tocType">
<xs:sequence>
<xs:element name="toc1"/>
<xs:element name="toc2"/>
<xs:element name="tocn"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="indexType">
<xs:sequence>
<xs:element name="index1"/>
<xs:element name="index2"/>
<xs:element name="indexn"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

Hope these help,
George
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top