Bob's Burgers
Meeskond
- Aleksei Kopõlov
- Sander Perens
Idee
XML/XSD/XSLT
XML
<?xml version="1.0" encoding="utf-8"?>
<Menu>
<Item Category="Dish" MenuCategorie="Main course">
<ItemName><![CDATA[Chicken & mushroom risotto]]></ItemName>
<ItemType>
<Type>Spicy</Type>
</ItemType>
<Portions>
<Portion PortionType="Small">
<PortionPrice Currency="€">10.95</PortionPrice>
<PortionSize>
<Size Units="g">300</Size>
<Size Units="Person">1</Size>
</PortionSize>
</Portion>
<Portion PortionType="Medium">
<PortionPrice Currency="€">19.95</PortionPrice>
<PortionSize>
<Size Units="g">600</Size>
<Size Units="Person">2</Size>
</PortionSize>
</Portion>
</Portions>
<Description>Looks good</Description>
<Ingredients>
<Ingredient Units="g" Quantity="50">Butter</Ingredient>
<Ingredient Units="g" Quantity="100">Bacon</Ingredient>
<Ingredient Units="g" Quantity="100">Rice</Ingredient>
<Ingredient Units="ml" Quantity="50">White wine</Ingredient>
</Ingredients>
<IntoleranceFreeFood>
<IntoleranceFree>Lactose Free</IntoleranceFree>
<IntoleranceFree>Gluten free</IntoleranceFree>
</IntoleranceFreeFood>
</Item>
<Item Category="Dish" MenuCategorie="Main course">
<ItemName><![CDATA[Pilaff]]></ItemName>
<ItemType>
<Type>Spicy</Type>
<Type>mediterranean</Type>
</ItemType>
<Portions>
<Portion PortionType="Small">
<PortionPrice Currency="€">5</PortionPrice>
<PortionSize>
<Size Units="g">300</Size>
<Size Units="Person">1</Size>
</PortionSize>
</Portion>
<Portion PortionType="Medium">
<PortionPrice Currency="€">6</PortionPrice>
<PortionSize>
<Size Units="g">600</Size>
<Size Units="Person">2</Size>
</PortionSize>
</Portion>
<Portion PortionType="Large">
<PortionPrice Currency="€">7</PortionPrice>
<PortionSize>
<Size Units="g">900</Size>
<Size Units="Person">3</Size>
</PortionSize>
</Portion>
</Portions>
<Description>Looks good</Description>
<Ingredients>
<Ingredient Units="g" Quantity="50">Butter</Ingredient>
<Ingredient Units="g" Quantity="100">Bacon</Ingredient>
<Ingredient Units="g" Quantity="100">Rice</Ingredient>
</Ingredients>
<IntoleranceFreeFood>
<IntoleranceFree>Lactose Free</IntoleranceFree>
<IntoleranceFree>Gluten free</IntoleranceFree>
</IntoleranceFreeFood>
</Item>
<Item Category="Dish" MenuCategorie="Dessert">
<ItemName><![CDATA[Classic Tiramisu]]></ItemName>
<ItemType>
<Type>Spicy</Type>
<Type>Sour</Type>
</ItemType>
<Portions>
<Portion PortionType="Small">
<PortionPrice Currency="€">10.95</PortionPrice>
<PortionSize>
<Size Units="g">300</Size>
<Size Units="Person">1</Size>
</PortionSize>
</Portion>
<Portion PortionType="Medium">
<PortionPrice Currency="€">19.95</PortionPrice>
<PortionSize>
<Size Units="g">600</Size>
<Size Units="Person">2</Size>
</PortionSize>
</Portion>
</Portions>
<Description>Looks good, tastes okay</Description>
<Ingredients>
<Ingredient Units="g" Quantity="50">Butter</Ingredient>
<Ingredient Units="g" Quantity="100">Bacon</Ingredient>
<Ingredient Units="g" Quantity="100">Rice</Ingredient>
<Ingredient Units="g" Quantity="50">White wine</Ingredient>
</Ingredients>
</Item>
<Item Category="Dish" MenuCategorie="Dessert">
<ItemName><![CDATA[Pavlova]]></ItemName>
<ItemType>
<Type>Sweet</Type>
</ItemType>
<Portions>
<Portion PortionType="Small">
<PortionPrice Currency="€">13.13</PortionPrice>
<PortionSize>
<Size Units="g">300</Size>
<Size Units="Person">2</Size>
</PortionSize>
</Portion>
<Portion PortionType="Large">
<PortionPrice Currency="€">27.99</PortionPrice>
<PortionSize>
<Size Units="g">600</Size>
<Size Units="Person">4</Size>
</PortionSize>
</Portion>
</Portions>
<Description>Pavlova typically garnished with strawberries, passionfruit, kiwifruit and cream. Pavlova is a meringue-based dessert named after the Russian ballerina Anna Pavlova. It is a meringue dessert with a crisp crust and soft, light inside, usually topped with fruit and whipped cream.</Description>
<Ingredients>
<Ingredient Units="g" Quantity="50">strawberries</Ingredient>
<Ingredient Units="g" Quantity="100">passionfruit</Ingredient>
<Ingredient Units="g" Quantity="100">kiwifruit</Ingredient>
<Ingredient Units="ml" Quantity="100">cream</Ingredient>
</Ingredients>
</Item>
<Item Category="Drink" MenuCategorie="Alcohol">
<ItemName><![CDATA[Jem Beam]]></ItemName>
<ItemType>
<Type>Whisky</Type>
</ItemType>
<Portions>
<Portion PortionType="Small">
<PortionPrice Currency="€">2.95</PortionPrice>
<PortionSize>
<Size Units="ml">30</Size>
<Size Units="Shots">1</Size>
</PortionSize>
</Portion>
<Portion PortionType="Medium">
<PortionPrice Currency="€">14.95</PortionPrice>
<PortionSize>
<Size Units="ml">300</Size>
<Size Units="Shots">10</Size>
</PortionSize>
</Portion>
</Portions>
<Description>Whisky</Description>
</Item>
<Item Category="Drink" MenuCategorie="Juice">
<ItemName><![CDATA[Apple juice]]></ItemName>
<ItemType>
<Type>Juice</Type>
</ItemType>
<Portions>
<Portion PortionType="Small">
<PortionPrice Currency="€">1.05</PortionPrice>
<PortionSize>
<Size Units="ml">200</Size>
</PortionSize>
</Portion>
<Portion PortionType="Medium">
<PortionPrice Currency="€">1.55</PortionPrice>
<PortionSize>
<Size Units="ml">300</Size>
</PortionSize>
</Portion>
</Portions>
<Description>Freshly pressed from green apples</Description>
</Item>
<Item Category="Drink" MenuCategorie="Water">
<ItemName><![CDATA[Still water]]></ItemName>
<ItemType>
<Type>Water</Type>
</ItemType>
<Portions>
<Portion PortionType="Small">
<PortionPrice Currency="€">1</PortionPrice>
<PortionSize>
<Size Units="ml">200</Size>
</PortionSize>
</Portion>
<Portion PortionType="Medium">
<PortionPrice Currency="€">1.50</PortionPrice>
<PortionSize>
<Size Units="ml">300</Size>
</PortionSize>
</Portion>
<Portion PortionType="Large">
<PortionPrice Currency="€">2</PortionPrice>
<PortionSize>
<Size Units="ml">500</Size>
</PortionSize>
</Portion>
</Portions>
<Description>From tap</Description>
</Item>
<Item Category="Drink" MenuCategorie="Alcohol">
<ItemName><![CDATA[Saku Kuld]]></ItemName>
<ItemType>
<Type>Beer</Type>
</ItemType>
<Portions>
<Portion PortionType="Small">
<PortionPrice Currency="€">3.50</PortionPrice>
<PortionSize>
<Size Units="ml">300</Size>
</PortionSize>
</Portion>
<Portion PortionType="Medium">
<PortionPrice Currency="€">5</PortionPrice>
<PortionSize>
<Size Units="ml">500</Size>
</PortionSize>
</Portion>
</Portions>
<Description>Saku Kuld is the finest beer of Estonia’s oldest brewery. It is the cream of the crop when it comes to beers. Saku Kuld is a masterpiece that entwines two centuries of brewing traditions with the latest technology.</Description>
</Item>
</Menu>
XSD
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Menu">
<xs:complexType>
<xs:sequence>
<xs:element name="Item" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="ItemName" type="xs:string" maxOccurs="1" minOccurs="1"/>
<xs:element name="ItemType" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Type" type ="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Portions" minOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Portion" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="PortionPrice" minOccurs="1" maxOccurs="1">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="Currency" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="PortionSize" minOccurs="1" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Size" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="Units" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="PortionType" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Description" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="Ingredients" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Ingredient" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Units" type="xs:string"/>
<xs:attribute name="Quantity" type="xs:decimal"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="IntoleranceFreeFood" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="IntoleranceFree" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Category" type="xs:string"/>
<xs:attribute name="MenuCategorie" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
XSLT HTML
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/Menu">
<html>
<style>
table {
border-collapse: collapse;
margin: 25px;
margin-bottom: 50px;
}
th, td {
border: 1px solid #ccc;
padding: 10px;
text-align: center;
}
td.exept{
text-align: left;
width:60%
}
</style>
<body>
<h1 align="center">Menu</h1>
<table>
<thead>
<tr class="border">
<td align="center" colspan="4">
<h2>Dishes</h2>
</td>
</tr>
<tr class="TableHead">
<th rowspan="2">Name</th>
<th colspan="3">Price</th>
</tr>
<tr>
<th>Small</th>
<th>Medium</th>
<th>Large</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="4">Main course</td>
</tr>
<xsl:for-each select="Item">
<xsl:if test="@Category='Dish' and @MenuCategorie = 'Main course'">
<xsl:apply-templates select="."/>
</xsl:if>
</xsl:for-each>
<tr>
<td colspan="4">Dessert</td>
</tr>
<xsl:for-each select="Item">
<xsl:if test="@Category='Dish' and @MenuCategorie = 'Dessert'">
<xsl:apply-templates select="."/>
</xsl:if>
</xsl:for-each>
</tbody>
</table>
<table>
<thead>
<tr class="border">
<td align="center" colspan="4">
<h2>Drinks</h2>
</td>
</tr>
<tr class="TableHead">
<th rowspan="2">Name</th>
<th colspan="3">Price</th>
</tr>
<tr>
<th>Small</th>
<th>Medium</th>
<th>Large</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="4">Alcohol</td>
</tr>
<xsl:for-each select="Item">
<xsl:if test="@Category='Drink'and @MenuCategorie = 'Alcohol'">
<xsl:apply-templates select="."/>
</xsl:if>
</xsl:for-each>
<tr>
<td colspan="4">Non-Alcohol</td>
</tr>
<xsl:for-each select="Item">
<xsl:if test="@Category='Drink'and @MenuCategorie != 'Alcohol'">
<xsl:apply-templates select="."/>
</xsl:if>
</xsl:for-each>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="Item">
<tr>
<td class="exept">
<xsl:value-of select="ItemName"/><br/>
Description:<xsl:value-of select="Description"/>
<br/>
<xsl:if test="IntoleranceFreeFood/IntoleranceFree">
Additional information:
<ul>
<xsl:for-each select="IntoleranceFreeFood/IntoleranceFree">
<li>
<xsl:value-of select="."/>
</li>
</xsl:for-each>
</ul>
</xsl:if>
</td>
<td>
<xsl:for-each select="Portions/Portion">
<xsl:if test="@PortionType = 'Small'">
<xsl:value-of select="PortionPrice"/>
<xsl:value-of select="PortionPrice/@Currency"/>
</xsl:if>
</xsl:for-each>
</td>
<td>
<xsl:for-each select="Portions/Portion">
<xsl:if test="@PortionType = 'Medium'">
<xsl:value-of select="PortionPrice"/>
<xsl:value-of select="PortionPrice/@Currency"/>
</xsl:if>
</xsl:for-each>
</td>
<td>
<xsl:for-each select="Portions/Portion">
<xsl:if test="@PortionType = 'Large'">
<xsl:value-of select="PortionPrice"/>
<xsl:value-of select="PortionPrice/@Currency"/>
</xsl:if>
</xsl:for-each>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
XSLT XML
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/Menu">
<Menu>
<xsl:for-each select="Item">
<Item>
<ItemName>
<xsl:value-of select="ItemName"/>
</ItemName>
<Description>
<xsl:value-of select="Description"/>
</Description>
<IntoleranceFreeFood>
<xsl:for-each select="IntoleranceFreeFood/IntoleranceFree">
<IntoleranceFree>
<xsl:value-of select="."/>
</IntoleranceFree>
</xsl:for-each>
</IntoleranceFreeFood>
<Portions>
<Portion>
<xsl:for-each select="Portions/Portion">
<PortionPrice>
<xsl:value-of select="PortionPrice"/>
<xsl:value-of select="PortionPrice/@Currency"/>
</PortionPrice>
<PortionSize>
<xsl:for-each select="PortionSize/Size">
<Size>
<xsl:value-of select="."/>
<xsl:value-of select="./@Units"/>
</Size>
</xsl:for-each>
</PortionSize>
</xsl:for-each>
</Portion>
</Portions>
<Ingredients>
<xsl:for-each select="Ingredients/Ingredient">
<Ingredient>
<xsl:value-of select="."/>
<xsl:value-of select="./@Quantity"/>
<xsl:value-of select="./@Units"/>
</Ingredient>
</xsl:for-each>
</Ingredients>
</Item>
</xsl:for-each>
</Menu>
</xsl:template>
</xsl:stylesheet>
Retsensioonid
XML Retsensioon meeskonnale VeebiGurmaanid
Esitatud XML fail on korrektselt vormistatud ja valideerub. Loogiliste dimensioonide mõõde vastab lähteülesande nõuetele. XML'is on kasutatud ühtlast stiili läbi kõikide elementide.
XSD's on määratud retseptID, autorId ja komponentId tüüpideks "unsignedByte", mille lubatud väärtused on 0...255. Kui retsepte ajaga kogunema hakkab, siis võivad kõik need atribuudid probleemiks saada. Parem oleks olnud kasutada mõnda tüüpi, mis lubab suuremaid väärtuseid, näiteks "int", "integer" või miks ka mitte "positiveInteger". Atribuudi "kogus" oleks võinud ehk ka decimali'ks teha, mis annaks rohkem vabadust sisestajale. Saaks sisestada näiteks 1,5 dl.
XML'is oleks võinud ehk kasutada ka CDATA't komponentide ja valmistamisjuhendite sisuosas. Atribuutide väärtuste osas ei oleks soovitatav kasutada täpitähti. Väärtusest "toiduõli" saab "toiduoli" ja see võib kokkulepitud formaati rikkuda. Retsepti nimetuse oleks võinud eraldi elemendiks teha, põhjuseks täpitähe teema ja kui keegi sisestab retsepti kus on mõni XML poolt parsitav sümbol sees, näiteks "sweet & sour", siis validatsioon ei õnnestu. Võiks ka kasutada escape charactere, näiteks & asemel & aga siis peavad retseptide sisestajad teadma mida nad tohivad ja mida nad ei tohi kirjutada.
XSLT'd on korrektsed ja on arusaadavad. On kasutatud tsükleid, tingimusi, atribuutide ja sisuosade kuvamist ja järjestamist.
Üldiselt arusaadav töö ja arusaadavalt teostatud.