Κατανεμημένες Εφαρμογές και Ηλεκτρονικό Εμπόριο -> XML

4 Επεξεργασία τεκμηρίων βασισμένων σε XML

4.1 Εισαγωγή

Σκοπός αυτής της ενότητας είναι να περιγράψει μερικούς τύπους διαθέσιμων επεξεργαστών, οι οποίοι παίρνουν ένα τεκμήριο εκφρασμένο σε γλώσσα XML και το DTD της γλώσσας και κάνουν κάτι σε αυτό, για παράδειγμα μετατρέπουν τα στοιχεία που περιγράφει η γλώσσα σε σειρές ενός σχεσιακού πίνακα.

Το κύριο εργαλείο που χρησιμοποιήθηκε από τους προγραμματιστές XML ήταν ένας σαρωτής. Ένας σαρωτής είναι ένα πρόγραμμα που παίρνει τον πόρο μιας γλώσσας και ελέγχει αν αντιστοιχεί ορθώς στον ορισμό του. Ένας σαρωτής XML θα ελέγξει ένα αρχείο XML σε σχέση με το DTD του.

Ο σαρωτής XML μπορεί να είναι επικυρωτικός ή μη. Ένας επικυρωτικός σαρωτής ελέγχει αν ένα XML αρχείο ανταποκρίνεται σε όλους τους κανόνες του DTD του. Ένας μη-επικυρωτικός σαρωτής θα εκτελέσει λιγότερους ελέγχους, όπως αν ένα επίθεμα συνοδεύεται κι από το αντίστοιχο ληκτικό.

4.2 Ένα παράδειγμα σαρωτή

Σ' αυτήν την ενότητα θα περιγράψω έναν απλό σαρωτή XML γνωστό ως Aelfred. Πρόκειται για έναν μη-επικυρωτικό σαρωτή. Αυτό τον κάνει μικρό στο μέγεθος και γρήγορο. Βασίζεται στην επεξεργασία κάποιου πηγαίου κώδικα και στην πυροδότηση μιας σειράς συμβάντων σχετικών με τα επιθέματα του αρχείου XML.

Οι μέθοδοι του σαρωτή Aelfred παρέχονται μέσω της διεπαφής XmlHandler. Οι σημαντικότερες μέθοδοι παραθέτονται παρακάτω.

Η μέθοδος startDocument εκτελείται όταν ένα αρχείο XML διαβάζεται για πρώτη φορά από τον σαρωτή Aelfred. Ομοίως, η μέθοδος endDocument εκτελείται όταν ο σαρωτής φθάσει στο τέλος του αρχείου.

Η μέθοδος startElement, η οποία έχει ένα αλαφαριθμητικό όρισμα, εκτελείται κάθε φορά που συναντάται το εισαγωγικό επίθεμα ενός στοιχείου, και κρατά το όνομα του επιθέματος ως το αλφαριθμητικό όρισμα. Έτσι, για παράδειγμα, ο κώδικας

  public void startElement(String tagName)
{
String currentTag = tagName;
..
}

θέτει την τοπική μεταβλητή currentTag ισοδύναμη με το όνομα του επιθέματος που μόλις έχει επεξεργαστεί.

Η μέθοδος endElement εκτελείται με την εύρεση ενός ληκτικού επιθέματος όπως το </TOWN>. Έχει ένα απλό αλφαριθμητικό όρισμα στο οποίο δίνεται η τιμή του επιθέματος.

Η μέθοδος charData έχει τρία ορίσματα: το πρώτο είναι ένα πίνακα χαρακτήρων, το δεύτερο και το τρίτο είναι ακέραιοι. Αυτή η μέθοδος εκτελεστεί όταν συναντώνται δεδομένα που περιέχουν επιθέματα και αλφαριθμητικά, για παράδειγμα όταν ο σαρωτής συναντήσει το αλφαριθμητικό  "Northamptonshire" στη παρακάτω γραμμή

<COUNTY>Northamptonshire</COUNTY>

Το πρώτο όρισμα κρατά όλους τους χαρακτήρες της γραμμής, το πρώτο ακέραιο όρισμα δεικτοδοτεί την αρχή των χαρακτήρων μέσα στη γραμμή,  το δεύτερο ακέραιο όρισμα δεικτοδοτεί το τέλος των χαρακτήρων. Έτσι ο κώδικας

  public void charData(char[] str, int first, int last)
{
String StrValue = new String(str, first, last);
..
}

θα εξάγει την στοιχειοσειρά "Northamptonshire" και θα την τοποθετήσει μέσα στο StrValue όταν συναντηθεί το απόσπασμα του παραπάνω πόρου.

Η τελευταία σημαντική μέθοδος είναι η attribute. Αυτό έχει τρία ορίσματα: το πρώτο είναι ένα αλφαριθμητικό που είναι το όνομα της ιδιότητας, το δεύτερο είναι ένα αλφαρθμητικό που κρατά την τιμή της ιδότητας και το τρίτο είναι μια λογική μεταβλητή που είναι αληθής αν η ιδιότητα ορίζεται μέσα στο τεκμήριο XML και ψευδής αν είναι μία προκαθορισμένη τιμή που ορίζεται στο DTD του τεκμηρίου. Για παράδειγμα, ο κώδικας

  public void attribute (String aName, String aValue, boolean found)
{
String attributeName = aName;
String attributeValue = aValue;
..
}

όταν επεξεργάζεται την σειρά

<TOWN NAME = "Towcester">

θέτει το attributeName ως το αλφαριθμητικό "NAME" και το attributeValue ως το αλφαριθμητικό "Towcester".

Ο Aelfred βασίζεται σε ένα μοντέλο συμβάντων που απαιτεί από τον προγραμματιστή να χρησιμοποιεί ένα τύπο προγραμματισμού που θυμάται τα συμφραζόμενα μέσα στα οποία συναντώνται τα συγκεκριμένα στοχεία της XML. Για παράδειγμα, ο κώδικας attribute δεν περιλαμβάνει ένα όρισμα που να προσδιορίζει το στοιχείο στο οποίο ανήκει η ιδιότητα: θα πρέπει να υπάρχει μνήμη αυτού του στοιχείου από μια προηγούμενη επίκληση του κώδικα startElement.

Ο παρακάτω κώδικας παρουσιάζει ένα παράδειγμα αυτών των μεθόδων στην πράξη. Ο κώδικας για κάθε μέθοδο που δεν περιέγραψα παραπάνω παραλείπεται. Παρέλειψα, επίσης, τις απαιτούμενες δηλώσεις εισαγωγής. Η εφαρμογή βασίζεται σε ένα applet.

  public class XMLApplet extends Applet implements XmlHandler
{

public void init()
{
//Code here to declara visual objects within the applet
//I shall assume that there is a text area known as tArea

//Code to initialise and lay out the visual objects
//on the applet not shown

//Set up the parser
private XmlParser parser;
parser = new XmlParser();

//Applet is the event handler for the parser
parser.setHandler(this);
..
}

//
//Start the event methods
//

public void start()
{
//Start the parser executing, the details are not shown
}


public void startDocument()
{
tArea.appendText("Document started" +"\n");
}

public void endDocument()
{
tArea.appendText("Document finished" +"\n");
}

public void startElement(String name)
{
tArea.appendText ("Start Element " +name+"processed"+"\n");
}

public void endElement(String name)
{
tArea.appendText("End Element " +name+"processed"+"\n");
}

public void charData (char[] stringValue, int first, int last)
{
String val = new String(stringValue, first, last);
tArea.appendText("Character string encountered "+val+"\n");
}

public void attribute (String aName, String aValue, boolean isSpecified)
{
tArea.appendText ("Attribute name = "+aName+
"Attribute value = "+aValue+"\n");
}

//Remainder of methods from XmlHandler
}

Σε αυτόν τον κώδικα η μέθοδος init του applet (η μέθοδος που εκτελείται πρώτη όταν applet γίνεται ορατό σε έναν  περιηγητή) πρώτα δημιουργεί έναν σαρωτή XML και στην συνέχεια εγγράφει το applet ως ακροατή για οποιοδήποτε γεγονός σάρωσης λαμβάνει χώρα. Καθένα από τα γεγονότα στην συνέχεια παγιδεύεται από τις μεθόδους που ακολουθούν.

Αυτό θα έχει ως τελικό αποτέλεσμα την εμφάνιση του κειμένου στο TextArea αντικείμενο tArea για το απόσπασμα XML:

<COUNTY NAME = "Northampton">
<POPULATION>
1356000
</POPULATION>
<TOWN SIZE = "556000">
Shoe industry
</TOWN>
</COUNTY>

Το κείμενο που εμφανίζεται είναι

Document started
Start Element COUNTY processed
Attribute name = NAME Attribute value = Northampton
Start Element POPULATION processed
Character string encountered 1356000
End Element POPULATION processed
Start Element TOWN processed
Attribute name = SIZE Attribute value = 556000
Character string encountered Shoe industry
End Element TOWN processed
End Element COUNTY processed
Document finished

Κάθε εμφάνιση επιθέματος, ληκτικού επιθέματος, ιδιότητας ή χαρακτήρων εκτελεί την αντίστοιχη μέθοδο στη διεπαφή XmlHandler.

Αυτό είναι ένα παράδειγμα διεπαφής σε ένα  αρχείο ορισμένο με XML. Υπάρχει ακόμα ένας τύπος διεπαφής που αξίζει να αναφέρουμε και εκεί είναι που, αντί για την πυροδότηση συμβάντων, χτίζεται ένα δέντρο, το οποίο περιγράφει το τεκμήριο και που μπορεί στην συνέχεια να υποστεί επεξεργασία από μεθόδους που προσπελαύνουν τους κόμβους του δέντρου. Αυτή είναι η ιδέα πίσω από το Document Object Model (DOM) που πρόσφατα τυποποιήθηκε από το W3 Consortium. Ένα παράδειγμα αυτού του δέντρου φαίνεται στο Σχήμα 8.2.

Η κύρια διαφορά μεταξύ του προγραμματισμού μίας αναπαράστασης DOM και του προγραμματισμού συμβάντων που αναλύθηκε προηγουμένως, είναι ότι στο τελευταίο πρέπει να παρακολουθείτε το πού βρίσκεστε, για παράδειγμα θα πρέπει να γνωρίζετε αν βρίσκεστε μέσα σε ένα επίθεμα το οποίο εσωκλείεται σε ένα άλλο, που κι αυτό, ίσως,  βρίσκεται μέσα σε ένα τρίτο. Αυτό απαιτεί δύσκολο και επιρρεπή σε λάθη προγραμματισμό. Όταν κάποιος προσπελάυνει μια παναπάσταση δέντρου αυτός ο τύπος πληροφορίας είναι έτοιμος.

Στο Σχήμα 8.2 το στοιχείο COUNTRY περιλαμβάνει ορισμένα στοιχεία COUNTY, με το δέντρο να δείχνει την μεταξύ τους ιεραρχική σχέση.

image


Αξίζει να τονίσουμε ότι η XML είναι μία συντακτική προσέγγιση στη σημειακή γλώσσα. Οι σημαντικές παρέχονται από τον κώδικα όπως περιγράφεται σ' αυτήν την ενότητα
Το μοντέλο DOM
Σχήμα 8.2
Ένα εσωτερικό δέντρο XML
Άσκηση 8.3
Χρησιμοποιώντας ένα DOM  API


Σαρωτές XML
Ο κώδικας χρησιμοποιεί έναν κατασκευαστή αλφαριθμητικών τριών ορισμάτων, ο οποίος σχηματίζει ένα αλφαριθμητικό στο πρώτο όρισμα μεταξύ των θέσεων που δεικτοδοτούνται από το δεύτερο και το τρίτο όρισμα
Ο Aelfred πήρε το όνομά του από τον βασιλιά Alfred της Αγγλίας (871-899 μ.Χ.) που πρωτοστάτησε στην λογοτεχνική αναγέννηση της χώρας
Αν η βασιζόμενη σε συμβάντα επεξεργασία σας έχει μπερδέψει λίγο, το Κεφάλαιο 4 περιλαμβάνει μία συζήτηση μέσα στα πλαίσια τω κατανεμημλενων  παραδειγμάτων.
Άσκηση 8.2
Επεξεργασία ενός DTD με την χρήση ενός σαρωτή
Αν νιώθετε μια σύγχυση όσον αφορά τις έννοιες της παγίδευσης συμβάντωντ και της εκτέλεσης μεθόδων, τότε αξίζει να πούμε ότι το μοντέλο είναι το ίδιο με αυτό που υιοθετήθηκε στην Java για τον χειρισμό συμβάντων όπως το πάτημα ενός κουμπιού: αυτό της εφαρμογής μιας διεπαφής για την εγγραφή ενός ακροατή και στην συνέχεια της παροχής ενός κώδικα για τις μεθόδους της διεπαφής
Άσκηση 8.4
Μετατροπή ενός καταλόγου XML σε σχεσιακή βάση