Πανεπιστήμιο Κρήτης Τμήμα Επιστήμης Υπολογιστών ΗΥ-561 Διαχείριση Δεδομένων στο Παγκόσμιο Ιστό Βασίλης Χριστοφίδης Ονοματεπώνυμο : Αριθμός Μητρώου: Τελική Εξέταση (3 ώρες) Ημερομηνία: Πέμπτη 19 Ιουλίου 2007 Άσκηση 1 (15 μονάδες) a) (6 μονάδες) Είναι το παρακάτω XML Σχήμα έγκυρο (valid) βάσει των προδιαγραφών XSD; Αν όχι, παραθέστε και εξηγήστε όλα τα λάθη. <xsd:complextype name= "ClassSize"> <xsd:restriction base="xsd:nonnegativeinteger"> <xsd:mininclusive value="10" fixed="true"/> <xsd:maxinclusive value="60"/> </xsd:complextype> <xsd:complextype name= "CSDClassSize"> <xsd:restriction base="classsize"> <xsd:mininclusive value="15"/> <xsd:maxinclusive value="60"/> </xsd:complextype> < xsd:complextype name= "CSDClassSize2" maxoccurs="unbounded"> <xsd:restriction base="classsize"> <xsd:mininclusive value="10"/> <xsd:maxinclusive value="60"/> </xsd:complextype> <xsd:element name="book" type="xsd:string"> <xsd:complextype> <xsd:sequence> <xsd:element name="title" type="xsd:string" minoccurs="1"/> <xsd:element name="author" type="xsd:string" minoccurs="1" /> <xsd:element name="date" type="xsd:string" maxoccurs="1"/> <xsd:element name="isbn" type="xsd:string" minoccurs="1"/> <xsd:element name="publisher" type="xsd:string" minoccurs="1"/>
ANSWER: No. The definition of ClassSize, CSDClassSize and CSDClassSize2 is xsd:simpletype definition and using complextype for them is wrong, since they don t have any child elements. (0.5 point for each of the class names) These are DTD definitions and not DTD declaration and hence the maxoccurs= "unbounded" is not allowed in the definition of CSDClassSize2. (1 point for the mistake and 0.5 point for the reason) Book declaration can t have a complextype child element and a type attribute at the same time. (1 point for mentioning the mistake and 0.5 for the reason) The mininclusive value is set to fixed in ClassSize definition and hence it shouldn t change in the CSDClassSize definition. (1 point for mentioning the mistake and 0.5 for the reason) b) (3 μονάδες) Είναι, ή όχι, ισοδύναμα το DTD και το XML Σχήμα που ακολουθεί; Εξηγήστε γιατί. DTD: <!ELEMENT Course (#PCDATA)> <!ATTLIST Course Department (CSCI EE MECH) #REQUIRED Grade (0 1 2 3 4) "0"> XSD: <xsd:element name="course"> <xsd:complextype> <xsd:attributegroup ref="courseattributes"/> </xsd:complextype> </xsd:element> <xsd:attributegroup name="courseattributes"> <xsd:attribute name="department"> <xsd:simpletype> <xsd:restriction base="xsd:string"> <xsd:enumeration value="csci"/> <xsd:enumeration value="ee"/> <xsd:enumeration value="mech"/> </xsd:simpletype> </xsd:attribute> <xsd:attribute name="grade"> <xsd:simpletype> <xsd:restriction base="xsd:integer"> <xsd:maxinclusive value="4"/> <xsd:minexclusive value="-1"/>
Answer: They are not. The attribute Department is set to required in the DTD but not in the XSD. (1 point) The attribute Grade has a default value equal to 0 in the DTD but not in the XSD. (1 point) In the DTD file, Course element can have a #PCDATA value, but the Course element in the XSD can only have an attribute. (1 point) c) (6 μονάδες) Γράψτε τις ενσωματωμένες δηλώσεις στοιχείων XML Σχήματος (XML Schema inline element declarations) που αντιστοιχούν στις παρακάτω δηλώσεις στοιχείων DTD (DTD element declarations). <!ELEMENT Burger (#PCDATA)> <!ATTLIST Burger Level (Bloody Pink Welldone) Welldone #REQUIRED> Answer: <xsd:element name="burger"> <xsd:complextype> <xsd:simplecontent> <xsd:extension base="xsd:string"> <xsd:attribute name="level" use="required" default="welldone"> <xsd:simpletype> <xsd:restriction base="xsd:string"> <xsd:enumeration value="bloody"/> <xsd:enumeration value="pink"/> <xsd:enumeration value="welldone"/> </xsd:simpletype> </xsd:attribute> </xsd:extension> </xsd:simplecontent> </xsd:complextype> </xsd:element> (0.5 point) for xsd:element and the corresponding closing tag. (1 point) for the complextype and the corresponding closing tag. (1 point) for the simplecontent and the corresponding closing tag. (1 point) for the extension tag (plus setting the base to string) and the corresponding closing tag. (0.5 point) for attribute definition ( element definition not accepted here ) (1 point) for SimpleType and the corresponding closing tag. Άσκηση 2 (35 μονάδες) 1. (10 μονάδες) Στις παρακάτω εκφράσεις XPath χρησιμοποιείται η συνοπτική σύνταξη. Δώστε τις ισοδύναμες εκδοχές πλήρους σύνταξης για τις εκφράσεις αυτές: (a) /doc/a[6]/b[2] (b) //gg
(c) *//.././/* (d) //*/[8] (e)../*/..[7]/a (a) /child::doc/child::a[position=6]/child::b[position=2] (b) /descendant-or-self::node()/child::gg (c) child::*/descendant-or-self::node()/parent::node() /self::node()/descendant-or-self::node()/child::* (d) /descendant-or-self::node()/child::*/child::node()[position=8] (e) parent::node()/child::*/parent::node()[position=7]/child::a 2. (15 μονάδες) Εξηγήστε σε φυσική γλώσσα το νόημα των παρακάτω επερωτήσεων: (a) [a/b/text() = 56] (b) [a/b/text()!= 56] (c) [not(a/b/text() = 56)] (a) The result of the query is true if the context node has a child with label a that has a child node with label b that has the text 56, otherwise it is false. (b) The result of the query is true if the context node has a child node with label a that has a child node with label b that does not have the text 56, otherwise it is false. (c) The result of the query is true if the context node does not have a child with label a, or has a child with node a that does not have a child node with label b that has the text 56, otherwise it is false. Notice that the query produces a Boolean value, not a list of nodes! (a) and (c) are each other s negation; (a) is true if and only if (c) is not true. (b) and (c) are different queries. For example, for a context node having both an a-child with a b-child with text 56 and an a-child with a b-child which has not the text 56, (b) will evaluate to true, while (c) evaluates to false. 3. (10 μονάδες) Ποια είναι τα αποτελέσματα των ακόλουθων δύο επερωτήσεων; let $doc := <a> <c> 4 </c> <c> 5 <b> 6 </b> </c> </a> for $i2 in $doc//c where not(every $i1 in $doc//b satisfies ($i1 << $i2)) return $i2/text() let $doc := <a> <c> 4 <b> 6 </b> </c> <c> 5 <b> 6 </b> </c> </a> for $i2 in $doc//c where not(every $i1 in $doc//b satisfies ($i1 << $i2)) return $i2/text()
Both queries return the list 4 5. Notice that the only difference between the two queries is in the value of the variable $doc. Both queries return the text of those elements e that have label c in the document $doc, that are descendants of the root node, and such that there is an element with label b in $doc that strictly follows e. The respective documents look like (tree representation; text is omitted): The elements that satisfy the given condition are circled. Notice that in the second tree, also the second element c is circled, because it suffices that there is one following node with label b; not all b-nodes need to follow c. In both cases, the text of the two cnodes is respectively 4 and 5. Άσκηση 3 (60 μονάδες) Θεωρείστε την παρακάτω σχεσιακή βάση Commodity: Products: pid Name Price Description 323 gizmo 22.99 great 233 gizmo plus 99.99 more features 312 gadget 59.99 good value Stores: Sid Name Phone s282 Wiz 555-1234 s521 Econo-Wiz 555-6543 Sells: Pid Markup sid 323 10% s521 233 25% s282 233 15% s521 a) (5 μονάδες) Θέλουμε να εξάγουμε τα δεδομένα αυτά σε ένα αρχείο XML. Γράψτε ένα DTD που περιγράφει την ακόλουθη δομή για το αρχείο XML: - Υπάρχει ένα ριζικό στοιχείο (root element) ονόματι stores - το στοιχείο stores περιέχει μία ακολουθία (sequence) από υποστοιχεία store, ένα για κάθε κατάστημα (store) στη βάση - κάθε στοιχείο store περιέχει ένα υποστιοχείο name, και ένα υποστοιχείο phone, καθώς και μία ακολουθία από υποστοιχεία product, ένα για κάθε προϊόν (product) που πωλείται από το κατάστημα. Επιπλέον, το στοιχείο store έχει ένα γνώρισμα (attribute) sid τύπου ID.
- κάθε στοιχείο product περιέχει ένα στοιχείο name, ένα price, ένα description, ένα markup, και ένα γνώρισμα pid τύπου ID. <!ELEMENT stores (store*)> <!ELEMENT store (name, phone, product*)> <!ELEMENT product (name, price, description, markup)> <!ELEMENT name #PCDATA> <!ELEMENT price #PCDATA> <!ELEMENT description #PCDATA> <!ELEMENT phone #PCDATA> <!ELEMENT markup #PCDATA> <!ATTLIST product pid ID #REQUIRED> b) (5 μονάδες) Γράψτε ένα έγγραφο XML που παράγεται από την εξαγωγή της βάσης Commodity στο DTD. <stores> <store sid = s282 > <name>wiz</name> <phone>555-1234</phone> <product pid = 233 > <name>gizmo plus</name> <price>99.99</price> <description>more features</description> <markup>25%</markup> </product> </store> <store sid = s521 > <name>econo-wiz</name> <phone>555-6543</phone> <product pid = 323 > <name>gizmo</name> <price>22.99</price> <description>great</description> <markup>10%</markup> </product> <product pid = 233 > <name>gizmo plus</name> <price>99.99</price> <description>more features</description> <markup>15%</markup> c) (20 μονάδες) Υποθέστε ότι έχετε το αρχείο εγγράφου XML ονόματι stores.xml με τη δομή που δόθηκε παραπάνω. Για κάθε ερώτηση που ακολυθεί, γράψτε μια επερώτηση XQuery. Επιπλέον, πείτε αν μπορεί να γραφεί μια απλή έκφραση XPath που ανακτά την ίδια πληροφορία. Αν ναι, δώστε την αντίστοιχη έκφραση XPath, αν όχι, αιτιολογήστε γιατί.
(i) Ποια καταστήματα πωλούν κάποια προϊόντα με τιμή υψηλότερη από 50; Παραθέστε τα ID τουs. Βεβαιωθείτε ότι κάθε ID καταστήματος παρατίθεται μία μόνο φορά. FOR $x IN distinct(document( stores.xml )//store[product/price> 50 ]/@sid) RETURN {$x} Store[product/price> 50 ]/name (ii) Ποια καταστήματα (εκτός του Wiz ) πωλούν τα ίδια προϊόντα με το κατάστημα Wiz ;? Παραθέστε τα ονόματά τουs. Το όνομα ενός καταστήματος μπορεί να εμφανιστεί μία ή περισσότερες φορές. FOR $x IN document( stores.xml )//store[name = Wiz ]/product FOR $y IN document( stores.xml )//store[name<> Wiz ] WHERE $x = $y/product RETURN {$y/name} ressed in XPath expressions, because there is no way to do join using XPath expressions. SOLUTION 2: LET $wiz := document( stores.xml )//store[name = Wiz ] FOR $s IN document( stores.xml )//store[name<> Wiz ] WHERE EVERY $pw IN $wiz/product SATISFIES EXISTS (FOR $p IN $s/product WHERE $p=$pw) RETURN {$s/name} Σημείωση: Η επερώτησή σας μπορεί να επιστρέψει τις απαραίτητες πληροφορίες με οποιοδήποτε σχήμα που είναι αναγνώσιμο. Για παράδειγμα, η απάντηση στην
(ι), μπορεί να περιλάβει μόνο τα ονόματα των καταστημάτων, ή τα ονόματα με τις ετικέτες τους (tags). d) (10 μονάδες) Θεωρείστε την ακόλουθη επερώτηση XQuery: <products> FOR $p IN distinct( stores.xml //product) RETURN <product> <name>{$p/name/text()}</name> <price>{$p/price/text()}</price> <description>{$p/description/text()}</description> { FOR $s IN distinct( stores.xml //store[product/pid = $p/pid]) RETURN <store> <name>$s/name/text()</name> <phone>$s/phone/text()</phone> { FOR $m IN stores.xml //store[sid = $s.sid]/ product[pid = $p.pid]/markup RETURN <markup>$m/text()</markup> } </store> Ποιο είναι το αποτέλεσμά της αν εκτελεσθεί για το έγγραφο XML της ερώτησης β; Δώστε το αρχείο XML του αποτελέσματος, καθώς και το DTD που περιγράφει τη δομή του.
<products> <product> <name>gizmo</name> <price>22.99</price> <description>great</description> <store> <name>econo-wiz</name> <phone>555-6543</phone> <markup>10%</markup> </store> </product> <product> <name>gizmo Plus</name> <price>99.99</price> <description>more features</description> <store> <name>wiz</name> <phone>555-1234</phone> <markup>25%</markup> </store> <store> <name>econo-wiz</name> <phone>555-6543</phone> <markup>15%</markup> </store> </product> </products> The DTD is <!ELEMENT products (product*)> <!ELEMENT product (name, price, description, store*)> <!ELEMENT store (name, phone, markup)> <!ELEMENT name #PCDATA> e) (20 μονάδες) (i) Θεωρήστε ότι έχετε ένα έγγραφο XML με τη δομή που δόθηκε παραπάνω. Γράψτε μια επερώτηση XQuery που επιστρέφει τα ονόματα και τις τιμές όλων των προϊόντων που πωλούνται σε όλα τα καταστήματα με markup όχι χαμηλότερο του 15%. Χάριν απλούστευσης, θεωρήστε ότι η έκφραση markup>= 15% καθορίζει ισοδύναμα ότι ένα markup δεν είναι χαμηλότερο του 15%. FOR $p IN distinct(document( stores.xml )//product) WHERE EVERY $m IN (document( stores.xml )//product[name = $p/name]/markup) SATISFIES $m >= 15% RETURN <result>{$p/name, $p/price}</result>
(ii) Τώρα, γράψτε την ίδια επερώτηση σε SQL έναντι της αρχικής σχεσιακής βάσης Commodity. Σημείωση: Το αποτέλεσμα δεν πρέπει να περιέχει διπλότυπα (duplicates). SELECT DISTINCT (name, price) FROM Products AS P1 WHERE NOT EXISTS( SELECT * FROM Products AS P2, Sells WHERE P1.pid = P2.pid AND P2.pid = Sells.pid AND Markup < 15% )