Rules:
- Root element is <quiz>.
- <quiz> contains a <title> and an <items> element.
- <items> contains one or more <item> element.
- <item> contains one <question>, at least 2
<answer>s, and no more than 6 <answer>s.
- One of the answer must have an attribute "correct=y"
which indicates the correct answer.
- <question> might appear before of after all the
<answer>s.
<?xml version="1.0"?>
<quiz>
<title>The Example Quiz</title>
<items>
<item>
<question>In which continent is the country Japan located?</question>
<answer correct="y">Asia</answer>
<answer>Europe</answer>
<answer>Africa</answer>
<answer>America</answer>
</item>
<item>
<answer>Tuna</answer>
<answer correct="y">Cow</answer>
<answer>Whale</answer>
<answer>Lobster</answer>
<question>Which one cannot swim?</question>
</item>
<item>
<question>How many points are on a hexagon?</question>
<answer>5</answer>
<answer>6</answer>
<answer>7</answer>
<answer correct="y">8</answer>
</item>
</items>
</quiz>
|
- A DTD declaration for that XML spec:
<!ELEMENT quiz (title, items)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT items (item)+>
<!ELEMENT item ((question, answer, answer+)|(answer, answer+, question))>
<!ELEMENT question (#PCDATA)>
<!ELEMENT answer (#PCDATA)>
<!ATTLIST answer correct (y) #IMPLIED>
|
XML with DTD
Problems:
- Hard to limit the number of <answer>s to 6
maximum. One way will be to declare it like:
<!ELEMENT item (question, ((answer, answer)|
(answer, answer, answer)|
(answer, answer, answer, answer)|
(answer, answer, answer, answer, answer)|
(answer, answer, answer, answer,answer,answer)))>
but do you want to?
Even with that, you still have to handle the requirement where
<question> might appear after the <answer>s, so it
will be:
<!ELEMENT item ((question, ((answer, answer)|
(answer, answer, answer)|
(answer, answer, answer, answer)|
(answer, answer, answer, answer, answer)|
(answer, answer, answer, answer,answer,answer)))|
(((answer, answer)|
(answer, answer, answer)|
(answer, answer, answer, answer)|
(answer, answer, answer, answer, answer)|
(answer, answer, answer, answer, answer, answer)), question))>
- The DTD does not limit the number of <answer>s that has
the "correct" attribute. So there might be an
<item> with 2 or more correct answers. Can this be solved
without changing the structure of the XML? Probably
not.
- Create a Schema declaration for that XML spec:
Attempt 1:
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="question" type="xsd:string"/>
<xsd:element name="answer">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="correct" type="xsd:string"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="itemType">
<xsd:sequence>
<xsd:element ref="question"/>
<xsd:element ref="answer" minOccurs="2" maxOccurs="6"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="item" type="itemType"/>
<xsd:complexType name="itemsType">
<xsd:sequence>
<xsd:element ref="item" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="items" type="itemsType"/>
<xsd:element name="quiz">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="title" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="items" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
|
Problems:
- <question> must appear before <answer>s in this
schema because it's declared in <xsd:sequence>.
- The <answer> attribute "correct" can be assigned
any values, while we only want to accept "y".
- This schema allows more than 1 correct <answer>s.
Again, it might not be possible to create a schema which prevents this.
Attempt 2:
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="question" type="xsd:string"/>
<xsd:simpleType name="correctType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="y"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="answer">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="correct" type="correctType"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="item">
<xsd:complexType>
<xsd:choice>
<xsd:sequence>
<xsd:element ref="question"/>
<xsd:element ref="answer" minOccurs="2" maxOccurs="6"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="answer" minOccurs="2" maxOccurs="6"/>
<xsd:element ref="question"/>
</xsd:sequence>
</xsd:choice>
</xsd:complexType>
</xsd:element>
<xsd:element name="items">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="item" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="quiz">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="title" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="items" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
|
This schema is much cleaner that before. We used a lot of
unnamed types because we don't need to reuse the types. "correctType"
is a type that contains only 1 valid value, which is "y". The <item> element is
declared within <xsd:choice> to allow <question> to appear
before or after the <answer>s.
Problems:
- This schema allows more than 1 correct <answer>s.
|
Displaying data using CSS style sheet.
- Style sheet
example 1
title
{
font-family:helvetica;font-size: 30px;display:block;color:red;
}
items
{
display: block;font-family:helvetica;font-size: 12px;color: black;
}
item
{
display: block;border:1px solid gray;margin: 3mm;font-family:helvetica;
font-size: 12px;color: black;
}
question
{
display: block;font-family:helvetica;font-size: 16px;
font-weight: bold;color: blue;
}
answer
{
display: block;font-family:helvetica;font-size: 12px;color: black;
}
|
Result on IE6:

- Style sheet
example 2
title
{
font-family:helvetica;
font-size: 30px;
display:block;
color:white;
background:rgb(0,0,0);
}
items
{
bacgkround:#DDDDDD;
display: block;
font-family:helvetica;
font-size: 12px;
color: black;
}
item
{
display: block;
margin: 0mm;
font-family:helvetica;
font-size: 12px;
color: black;
}
question
{
display: block;
font-family:helvetica;
font-size: 16px;
font-weight: bold;
color: blue;
position: relative;
background:#DDDDDD;
border: solid 1px;
}
answer
{
display: block;
position:relative;
left:50px;
font-family:helvetica;
font-size: 12px;
color: black;
background:#DDDD88;
}
|
Result on IE6:

- Style sheet 3 (show questions
only)
The answer element style is set to visibility: hidden.
title
{
font-family:helvetica;
font-size: 30px;
display:block;
color:white;
background:rgb(0,0,0);
}
item
{
display: block;
font-family:helvetica;
font-size: 12px;
color: black;
}
question
{
display: block;
font-family:helvetica;
font-size: 16px;
color: black;
}
answer
{
visibility: hidden;
}
|
Result on IE6:

Displaying Data Using XSLT.
This XSLT is almost identical to the one above, except this one
ignores any <answer> that does not have the attribute correct="y";
and also, this one puts each <item> inside a table cell.
Result on IE6:
<?xml version="1.0"?>
<quiz:stylesheet
xmlns:quiz="http://www.w3.org/1999/XSL/Transform" version="1.0">
<quiz:template match="/">
<html>
<head><title>Quiz Example formatted with XSLT</title></head>
<body><quiz:apply-templates/></body>
</html>
</quiz:template>
<quiz:template match="title">
</quiz:template>
<quiz:template match="item">
<quiz:for-each select="answer">
<quiz:choose>
<quiz:when test="@correct='y'">
<P/><font color="black"><B>
<quiz:value-of select="."/></B> is the correct answer for:
</font>
<font color="red">
<I><quiz:value-of select="../question"/></I>
</font>
</quiz:when>
</quiz:choose>
</quiz:for-each>
</quiz:template>
</quiz:stylesheet>
|
This XSLT ignores the <title> element. It then selects and prints the correct answer. Following that, it uses
XPath to find the <question> and prints the question.
Result on IE6:
<<INDEX>>
(C) 2002 F. Permadi
|