Προγραμματισμός

Προγραμματισμός XML σε Java, Μέρος 1

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

TEXTBOX: TEXTBOX_HEAD: Προγραμματισμός XML σε Java: Διαβάστε ολόκληρη τη σειρά!

  • Μέρος 1. Χρησιμοποιήστε το Simple API για XML (SAX) για να επεξεργαστείτε εύκολα το XML στην Java
  • Μέρος 2. Μάθετε για την επικύρωση SAX και XML μέσω επεξηγηματικών παραδειγμάτων
  • Μέρος 3. DOMination: Πάρτε τον έλεγχο των δομημένων εγγράφων με το μοντέλο αντικειμένου εγγράφου

: END_TEXTBOX

Αυτό το άρθρο αποτελεί συνέχεια του εισαγωγικού μου άρθρου, "XML για τον απόλυτο αρχάριο", στο τεύχος του Απριλίου 1999 του JavaWorld (ανατρέξτε στην ενότητα Πόροι παρακάτω για τη διεύθυνση URL). Αυτό το άρθρο περιέγραψε το XML. Θα βασιστώ τώρα σε αυτήν την περιγραφή και θα δείξω λεπτομερώς πώς να δημιουργήσω μια εφαρμογή που χρησιμοποιεί το Simple API για Java (SAX), ένα ελαφρύ και ισχυρό τυπικό Java API για την επεξεργασία XML.

Το παράδειγμα κώδικα που χρησιμοποιείται εδώ χρησιμοποιεί το SAX API για να διαβάσει ένα αρχείο XML και να δημιουργήσει μια χρήσιμη δομή αντικειμένων. Όταν ολοκληρώσετε αυτό το άρθρο, θα είστε έτοιμοι να δημιουργήσετε τις δικές σας εφαρμογές που βασίζονται σε XML.

Η αρετή της τεμπελιάς

Ο Larry Wall, δημιουργός της τρελής ιδιοφυΐας του Perl (η δεύτερη μεγαλύτερη γλώσσα προγραμματισμού που υπάρχει), δήλωσε ότι η τεμπελιά είναι μία από τις «τρεις μεγάλες αρετές» ενός προγραμματιστή (οι άλλες δύο είναι ανυπομονησία και αδράνεια). Η τεμπελιά είναι μια αρετή επειδή ένας τεμπέλης προγραμματιστής θα καταβάλει σχεδόν κάθε προσπάθεια για να αποφύγει τη δουλειά, ακόμη και μέχρι τη δημιουργία γενικών, επαναχρησιμοποιήσιμων πλαισίων προγραμματισμού που μπορούν να χρησιμοποιηθούν επανειλημμένα. Η δημιουργία τέτοιων πλαισίων συνεπάγεται πολλή δουλειά, αλλά ο χρόνος που εξοικονομείται σε μελλοντικές αναθέσεις δεν υπερβαίνει την αρχική προσπάθεια που επενδύθηκε. Τα καλύτερα πλαίσια επιτρέπουν στους προγραμματιστές να κάνουν εκπληκτικά πράγματα με λίγη ή καθόλου δουλειά - και γι 'αυτό η τεμπελιά είναι ενάρετη.

Το XML είναι μια τεχνολογία που επιτρέπει τον ενάρετο (τεμπέλης) προγραμματιστή. Ένας βασικός αναλυτής XML κάνει μεγάλη δουλειά για τον προγραμματιστή, αναγνωρίζοντας διακριτικά, μεταφράζοντας κωδικοποιημένους χαρακτήρες, επιβάλλοντας κανόνες σχετικά με τη δομή αρχείων XML, ελέγχοντας την εγκυρότητα ορισμένων τιμών δεδομένων και πραγματοποιώντας κλήσεις σε κώδικα για συγκεκριμένες εφαρμογές, όπου απαιτείται. Στην πραγματικότητα, η πρώιμη τυποποίηση, σε συνδυασμό με μια έντονα ανταγωνιστική αγορά, παρήγαγε αποτελέσματα ελευθερώς διαθέσιμες υλοποιήσεις τυπικών προγραμμάτων ανάλυσης XML σε πολλές γλώσσες, όπως C, C ++, Tcl, Perl, Python και, φυσικά, Java.

Το SAX API είναι μία από τις απλούστερες και πιο ελαφριές διεπαφές για το χειρισμό XML. Σε αυτό το άρθρο, θα χρησιμοποιήσω την εφαρμογή XX4J της IBM του SAX, αλλά επειδή το API είναι τυποποιημένο, η εφαρμογή σας θα μπορούσε να αντικαταστήσει οποιοδήποτε πακέτο που εφαρμόζει το SAX.

Το SAX είναι ένα API βάσει συμβάντων, το οποίο λειτουργεί βάσει της αρχής επανάκλησης. Ένας προγραμματιστής εφαρμογών θα δημιουργήσει συνήθως ένα SAX Αναλυτής αντικείμενο, και περάστε το και τα δύο εισάγετε XML και a χειριστής εγγράφων, που λαμβάνει επιστροφές κλήσεων για εκδηλώσεις SAX. Το SAX Αναλυτής μετατρέπει την είσοδό του σε μια ροή εκδηλώσεις αντιστοιχεί σε δομικά χαρακτηριστικά της εισόδου, όπως ετικέτες XML ή μπλοκ κειμένου. Καθώς συμβαίνει κάθε συμβάν, μεταφέρεται στην κατάλληλη μέθοδο ενός χειριστή εγγράφων που καθορίζεται από τον προγραμματιστή, η οποία εφαρμόζει τη διεπαφή επανάκλησης org.xml.sax.DocumentHandler. Οι μέθοδοι σε αυτήν την κατηγορία χειριστή εκτελούν τη λειτουργικότητα για συγκεκριμένη εφαρμογή κατά τη διάρκεια της ανάλυσης.

Για παράδειγμα, φανταστείτε ότι ένας αναλυτής SAX λαμβάνει ένα έγγραφο που περιέχει το μικροσκοπικό έγγραφο XML που εμφανίζεται στην λίστα 1 παρακάτω. (Δείτε πόρους για το αρχείο XML.)

 Ogden Nash Fleas Adam Had τους. 

Λίστα 1. XML που αντιπροσωπεύει ένα σύντομο ποίημα

Όταν ο αναλυτής SAX συναντά το ετικέτα, καλεί τον καθορισμένο από τον χρήστη DocumentHandler.startElement () με τη χορδή ΠΟΙΗΜΑ ως επιχείρημα. Εφαρμόζετε το startElement () μέθοδος για να κάνετε ό, τι η εφαρμογή πρόκειται να κάνει όταν ΠΟΙΗΜΑ ξεκινά. Η ροή συμβάντων και οι προκύπτουσες κλήσεις για το κομμάτι XML παραπάνω εμφανίζεται στον Πίνακα 1 παρακάτω.

Πίνακας 1. Η ακολουθία των επιστροφών SAX παράγει κατά την ανάλυση της καταχώρισης 1
Παρουσιάστηκε αντικείμενοΑναλυτική επιστροφή κλήσης
{Έναρξη εγγράφου}startDocument ()
startElement ("POEM", {AttributeList}))
"\ n"χαρακτήρες ("\ n ...", 6, 1)
startElement ("AUTHOR", {AttributeList}))
"Ogden Nash"χαρακτήρες ("\ n ...", 15, 10)
endElement ("ΣΥΓΓΡΑΦΕΙΣ")
"\ n"χαρακτήρες ("\ n ...", 34, 1)
startElement ("ΤΙΤΛΟΣ", {AttributeList})
"Ψύλλοι"χαρακτήρες ("\ n ...", 42, 5)
endElement ("ΤΙΤΛΟΣ")
"\ n"χαρακτήρες ("\ n ...", 55, 1)
startElement ("LINE", {AttributeList}))
"Αδάμ"χαρακτήρες ("\ n ...", 62, 4)
endElement ("ΓΡΑΜΜΗ")
startElement ("LINE", {AttributeList}))
"Είχαν."χαρακτήρες ("\ n ...", 67, 8)
endElement ("ΓΡΑΜΜΗ")
"\ n"χαρακτήρες ("\ n ...", 82, 1)
endElement ("POEM")
{Τέλος εγγράφου}endDocument ()

Δημιουργείτε μια τάξη που εφαρμόζει Έγγραφο χειριστή για να απαντήσετε σε συμβάντα που εμφανίζονται στο πρόγραμμα ανάλυσης SAX. Αυτά τα εκδηλώσεις δεν είναι εκδηλώσεις Java, όπως μπορεί να τα γνωρίζετε από το Abstract Windowing Toolkit (AWT). Πρόκειται για συνθήκες που ανιχνεύει ο αναλυτής SAX καθώς αναλύει, όπως η έναρξη ενός εγγράφου ή η εμφάνιση μιας ετικέτας κλεισίματος στη ροή εισόδου. Καθώς συμβαίνει κάθε μία από αυτές τις συνθήκες (ή συμβάντα), το SAX καλεί τη μέθοδο που αντιστοιχεί στη συνθήκη σε αυτήν Έγγραφο χειριστή.

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

Ο Πίνακας 1 δείχνει μόνο συμβάντα που σχετίζονται με στοιχεία και χαρακτήρες. Το SAX περιλαμβάνει επίσης διευκολύνσεις για τον χειρισμό άλλων δομικών χαρακτηριστικών των αρχείων XML, όπως οντότητες και οδηγίες επεξεργασίας, αλλά αυτές δεν εμπίπτουν στο πεδίο αυτού του άρθρου.

Ο έξυπνος αναγνώστης θα παρατηρήσει ότι ένα έγγραφο XML μπορεί να αναπαρασταθεί ως ένα δέντρο με δακτυλογραφημένα αντικείμενα και ότι η σειρά της ροής των συμβάντων που παρουσιάζεται στο Έγγραφο χειριστή αντιστοιχεί σε μια διαδοχική, πρώτη βάθος διάβαση του δέντρου εγγράφων. (Δεν είναι απαραίτητο να κατανοήσουμε αυτό το σημείο, αλλά η έννοια ενός εγγράφου XML ως δομή δέντρων δεδομένων είναι χρήσιμη σε πιο εξελιγμένους τύπους επεξεργασίας εγγράφων, τα οποία θα καλυφθούν σε μεταγενέστερα άρθρα αυτής της σειράς.)

Το κλειδί για την κατανόηση του τρόπου χρήσης του SAX είναι η κατανόηση του Έγγραφο χειριστή διεπαφή, την οποία θα συζητήσω στη συνέχεια.

Προσαρμόστε το πρόγραμμα ανάλυσης με το org.xml.sax.DocumentHandler

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

Αρχικοποίηση και εκκαθάριση εγγράφων

Για κάθε έγγραφο που αναλύεται, ο αναλυτής SAX XML καλεί το Έγγραφο χειριστή μεθόδους διεπαφής startDocument () (κλήθηκε πριν ξεκινήσει η επεξεργασία) και endDocument () (καλείται μετά την ολοκλήρωση της επεξεργασίας). Μπορείτε να χρησιμοποιήσετε αυτές τις μεθόδους για να προετοιμάσετε το δικό σας Έγγραφο χειριστή για να το προετοιμάσετε για τη λήψη συμβάντων και για τον καθαρισμό ή την παραγωγή εξόδου μετά την ολοκλήρωση της ανάλυσης. endDocument () είναι ιδιαίτερα ενδιαφέρον, δεδομένου ότι καλείται μόνο εάν ένα έγγραφο εισαγωγής έχει αναλυθεί με επιτυχία. Εάν το Αναλυτής δημιουργεί ανεπανόρθωτο σφάλμα, απλώς διακόπτει τη ροή συμβάντων και σταματά την ανάλυση και endDocument () δεν καλείται ποτέ.

Επεξεργασία ετικετών

Οι κλήσεις αναλυτή SAX startElement () όποτε συναντά μια ανοιχτή ετικέτα, και endElement () όποτε συναντά μια κλειστή ετικέτα. Αυτές οι μέθοδοι συχνά περιέχουν τον κώδικα που κάνει το μεγαλύτερο μέρος της εργασίας ενώ αναλύει ένα αρχείο XML. startElement ()Το πρώτο όρισμα είναι μια συμβολοσειρά, που είναι το όνομα της ετικέτας του στοιχείου που αντιμετωπίστηκε. Το δεύτερο επιχείρημα είναι ένα αντικείμενο τύπου Λίστα χαρακτηριστικών, μια διεπαφή που ορίζεται στο πακέτο org.xml.sax που παρέχει διαδοχική ή τυχαία πρόσβαση σε χαρακτηριστικά στοιχείων με το όνομα. (Αναμφίβολα έχετε δει χαρακτηριστικά στο HTML, στη γραμμή

, ΣΥΝΟΡΟ είναι ένα χαρακτηριστικό του οποίου η τιμή είναι "1"). Δεδομένου ότι η Λίστα 1 δεν περιλαμβάνει χαρακτηριστικά, δεν εμφανίζονται στον Πίνακα 1. Θα δείτε παραδείγματα χαρακτηριστικών στο δείγμα εφαρμογής αργότερα σε αυτό το άρθρο.

Δεδομένου ότι το SAX δεν παρέχει πληροφορίες σχετικά με το πλαίσιο των στοιχείων που συναντά (δηλαδή εμφανίζεται μέσα στην λίστα 1 παραπάνω, για παράδειγμα), εξαρτάται από εσάς να παρέχετε αυτές τις πληροφορίες. Οι προγραμματιστές εφαρμογών χρησιμοποιούν συχνά στοίβες στο startElement () και endElement (), ωθώντας αντικείμενα σε μια στοίβα όταν ξεκινά ένα στοιχείο και βγαίνοντας από τη στοίβα όταν τελειώσει το στοιχείο.

Επεξεργασία μπλοκ κειμένου

ο χαρακτήρες () Η μέθοδος δείχνει το περιεχόμενο χαρακτήρων στο έγγραφο XML - χαρακτήρες που δεν εμφανίζονται μέσα σε μια ετικέτα XML, με άλλα λόγια. Η υπογραφή αυτής της μεθόδου είναι λίγο περίεργη. Το πρώτο όρισμα είναι ένας πίνακας byte, ο δεύτερος είναι ένας δείκτης σε αυτόν τον πίνακα που υποδεικνύει τον πρώτο χαρακτήρα της περιοχής που θα υποβληθεί σε επεξεργασία και το τρίτο όρισμα είναι το μήκος της περιοχής χαρακτήρων.

Φαίνεται ότι ένα ευκολότερο API θα είχε περάσει απλά ένα Σειρά αντικείμενο που περιέχει τα δεδομένα, αλλά χαρακτήρες () ορίστηκε με αυτόν τον τρόπο για λόγους αποτελεσματικότητας. Ο αναλυτής δεν έχει κανέναν τρόπο να γνωρίζει εάν πρόκειται να χρησιμοποιήσετε τους χαρακτήρες ή όχι, έτσι ώστε ο αναλυτής να αναλύει το buffer εισόδου του, περνά μια αναφορά στο buffer και τους δείκτες της συμβολοσειράς που βλέπει, εμπιστεύοντας ότι θα δημιουργήσετε το δικό σου Σειρά αν θέλετε ένα. Είναι λίγο περισσότερη δουλειά, αλλά σας επιτρέπει να αποφασίσετε εάν θα επιβαρυνθείτε ή όχι Σειρά κατασκευή για κομμάτια περιεχομένου σε ένα αρχείο XML.

ο χαρακτήρες () Η μέθοδος χειρίζεται τόσο το κανονικό περιεχόμενο κειμένου όσο και το περιεχόμενο εντός των τμημάτων CDATA, τα οποία χρησιμοποιούνται για να αποτρέψουν την ανάλυση των μπλοκ του κυριολεκτικού κειμένου από έναν αναλυτή XML.

Άλλες μέθοδοι

Υπάρχουν τρεις άλλες μέθοδοι στο Έγγραφο χειριστή διεπαφή: αγνόητος Λευκός Χώρος (), επεξεργασίαΔιδασκαλία (), και setDocumentLocator (). αγνόητος Λευκός Χώρος () αναφέρει εμφανίσεις λευκού χώρου και συνήθως δεν χρησιμοποιείται σε μη επικυρωμένους αναλυτές SAX (όπως αυτός που χρησιμοποιούμε για αυτό το άρθρο). επεξεργασίαΔιδασκαλία () χειρίζεται τα περισσότερα πράγματα μέσα και ?> οριοθέτες? και setDocumentLocator () προαιρετικά εφαρμόζεται από τους αναλυτές SAX για να σας δώσει πρόσβαση στις τοποθεσίες των συμβάντων SAX στην αρχική ροή εισόδου. Μπορείτε να διαβάσετε αυτές τις μεθόδους ακολουθώντας τους συνδέσμους στις διεπαφές SAX στο Resources.

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

HandlerBase: Μια τάξη χωρίς τίποτα

Συχνά, σας ενδιαφέρει μόνο να εφαρμόσετε μία ή δύο μεθόδους σε μια διεπαφή και θέλετε οι άλλες μέθοδοι να μην κάνουν τίποτα. Η τάξη org.xml.sax.HandlerBase απλοποιεί την εφαρμογή του Έγγραφο χειριστή διεπαφή με την εφαρμογή όλων των μεθόδων διεπαφής με σώματα do-τίποτα. Τότε, αντί να εφαρμοστεί Έγγραφο χειριστή, μπορείτε να κάνετε υποκατηγορία Βάση χειριστήκαι αντικαθιστάτε μόνο τις μεθόδους που σας ενδιαφέρουν.

Για παράδειγμα, ας υποθέσουμε ότι θέλετε να γράψετε ένα πρόγραμμα που μόλις εκτύπωσε τον τίτλο οποιουδήποτε ποιήματος με μορφή XML (όπως Εύρεση τίτλου στην καταχώριση 1). Θα μπορούσατε να ορίσετε ένα νέο Έγγραφο χειριστή, όπως αυτή που περιλαμβάνεται στη λίστα 2 παρακάτω, αυτή η υποκατηγορία Βάση χειριστήκαι αντικαθιστά μόνο τις μεθόδους που χρειάζεστε. (Δείτε πόρους για ένα αρχείο HTML του Εύρεση τίτλου.)

012 / ** 013 * SAX DocumentHandler class που εκτυπώνει τα περιεχόμενα του στοιχείου "TITLE" 014 * ενός εγγράφου εισαγωγής. 015 * / 016 δημόσια κλάση TitleFinder επεκτείνει το HandlerBase {017 boolean _isTitle = false; 018 δημόσιο TitleFinder () {019 super (); 020} 021 / ** 022 * Εκτυπώστε οποιοδήποτε κείμενο βρίσκεται μέσα σε ένα  στοιχείο. 023 * / 024 δημόσιοι χαρακτήρες κενού (char [] chars, int iStart, int iLen) {025 if (_isTitle) {026 String sTitle = new String (chars, iStart, iLen); 027 System.out.println ("Τίτλος:" + sTitle); 028} 029} 030 / ** 031 * Επισήμανση στοιχείου τίτλου στο τέλος. 032 * / 033 public void endElement (Στοιχείο συμβολοσειράς) {034 if (element.equals ("TITLE")) {035 _isTitle = false; 036} 037} 038 / ** 039 * Βρείτε τα περιεχόμενα των τίτλων 040 * / 041 δημόσιο στατικό άκυρο κύριο (String args []) {042 TitleFinder titleFinder = new TitleFinder () 043 δοκιμάστε το {044 Parser parser = ParserFactory.makeParser ("com.ibm.xml.parsers.SAXParser"); 045 parser.setDocumentHandler (titleFinder); 046 parser.parse (νέο InputSource (args [0])); 047} αλίευση (εξαίρεση ex) {048; // Εντάξει, οπότε μερικές φορές η τεμπελιά * δεν είναι αρετή. 049} 050} 051 / ** 052 * Επισήμανση στοιχείου τίτλου έναρξης 053 * / 054 δημόσιο άκυρο startElement (Στοιχείο συμβολοσειράς, AttributeList attrlist) {055 if (element.equals ("TITLE")) {056 _isTitle = true; 057} 058} 

Λίστα 2. ΤίτλοςFinder: Ένα DocumentHandler που προέρχεται από το HandlerBase που εκτυπώνει TITLEs

Copyright el.verticalshadows.com 2023