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

Το XSLT ανθίζει με Java

Έχετε ποτέ συγκλονιστεί από ένα δύσκολο ζήτημα μετασχηματισμού XML που δεν θα μπορούσατε να επιλύσετε μόνο με το XSLT (Extensible Stylesheet Language Transformation); Πάρτε, για παράδειγμα, ένα απλό φύλλο στυλ φίλτρου που επιλέγει μόνο αυτά κόμβοι με ημερομηνία νωρίτερα από πέντε ημέρες πριν. Έχετε ακούσει ότι το XSLT μπορεί να φιλτράρει έγγραφα XML, οπότε πιστεύετε ότι θα λύσετε αυτό το πρόβλημα σε χρόνο μηδέν. Η πρώτη εργασία είναι η λήψη της σημερινής ημερομηνίας από ένα φύλλο στυλ, υπό την προϋπόθεση ότι οι πληροφορίες δεν περιλαμβάνονται στο αρχικό έγγραφο XML. Δυστυχώς, δεν μπορείτε να ολοκληρώσετε αυτήν την εργασία μόνο με XSLT. Σε μια κατάσταση όπως αυτή, μπορείτε να απλοποιήσετε τον κωδικό XSLT και να επιλύσετε το πρόβλημα πιο γρήγορα με μια επέκταση Java.

Πολλοί επεξεργαστές XSLT επιτρέπουν κάποιο τύπο μηχανισμού επέκτασης. η προδιαγραφή τους απαιτεί να το κάνουν. Στον κόσμο της Java και της XML, ο πιο διαδεδομένος επεξεργαστής XSLT είναι ο ανοιχτής πηγής επεξεργαστής Apache Xalan. Γράφοντας στην Java, το Xalan επιτρέπει επεκτάσεις στην Java. Πολλοί προγραμματιστές θεωρούν την επεκτασιμότητα του Xalan ισχυρή, επειδή τους επιτρέπει να αξιοποιήσουν τις δεξιότητές τους στο Java από το πλαίσιο του φύλλου στυλ. Εξετάστε τον τρόπο με τον οποίο τα JSP (JavaServer Pages), scriptlets και προσαρμοσμένες ετικέτες προσθέτουν ισχύ στο HTML. Οι επεκτάσεις Xalan προσθέτουν ισχύ στα φύλλα στυλ με τον ίδιο τρόπο: επιτρέποντας στους προγραμματιστές Java πρόσβαση στο αγαπημένο τους εργαλείο, Java.

Σε αυτό το άρθρο, θα δείξω πώς μπορείτε να χρησιμοποιήσετε το Java μέσα από ένα φύλλο στυλ XSLT. Πρώτον, θα χρησιμοποιήσουμε την επεκτασιμότητα του Xalan για να δημιουργήσουμε και να χρησιμοποιήσουμε υπάρχουσες τάξεις στο JDK. Αργότερα, θα σας δείξω πώς να γράψετε μια συνάρτηση επέκτασης XSLT που απαιτεί Σειρά όρισμα και επιστρέφει ένα τμήμα DOM (Document Object Model) στον επεξεργαστή φύλλου στυλ.

Το XSLT είναι σημαντικό για τους προγραμματιστές J2EE (Java 2 Platform, Enterprise Edition), επειδή το στυλ των εγγράφων XML έχει γίνει λειτουργία από την πλευρά του διακομιστή. Επίσης, το JAXP (το Java API for XML Processing), το οποίο περιλαμβάνει υποστήριξη για κινητήρες XSLT, έχει γίνει μέρος της προδιαγραφής J2EE (J2EE 2.6.11). Στην παιδική του ηλικία, το XSLT προοριζόταν για το στυλ XML στον πελάτη. Ωστόσο, οι περισσότερες εφαρμογές διαμορφώνουν το XML πριν από την αποστολή στον πελάτη. Για προγραμματιστές J2EE, αυτό σημαίνει ότι ο επεξεργαστής XSLT πιθανότατα θα εκτελείται εντός του διακομιστή εφαρμογών.

Πριν συνεχίσετε με αυτό το άρθρο, λάβετε υπόψη ότι η χρήση επεκτάσεων Java στα φύλλα στυλ XSLT θα μειώσει τη φορητότητά τους. Ενώ οι επεκτάσεις αποτελούν μέρος της προδιαγραφής XSLT, ο τρόπος εφαρμογής τους δεν είναι. Εάν τα φύλλα στυλ σας θα εκτελούνται σε επεξεργαστές διαφορετικούς από το Xalan, όπως η μηχανή στυλ στυλ του Internet Explorer, θα πρέπει να αποφύγετε τη χρήση επεκτάσεων με κάθε κόστος.

Αδυναμίες XSLT

Επειδή το XSLT έχει κάποια αδύναμα σημεία, οι επεκτάσεις XSLT αποδεικνύονται αρκετά χρήσιμες. Δεν λέω ότι το XSLT είναι κακό. Ωστόσο, απλώς δεν προσφέρει το καλύτερο εργαλείο για την επεξεργασία όλων σε ένα έγγραφο XML. Εξετάστε αυτήν την ενότητα του XML:

 Το XSLT δεν είναι τόσο εύκολο στη χρήση όσο κάποιοι θα σας… 

Ας υποθέσουμε ότι το αφεντικό σας σας ζητά να τροποποιήσετε ένα φύλλο στυλ ώστε να μετατρέπει όλες τις εμφανίσεις του "δεν" σε "δεν είναι" και εντοπίζει τις κοινές ετικέτες. Σίγουρα το XSLT παρέχει έναν μηχανισμό για να κάνει κάτι τέτοιο, σωστά; Λανθασμένος. Το XSLT δεν παρέχει εύκολο τρόπο αντικατάστασης της εμφάνισης μιας λέξης ή μοτίβου σε μια συμβολοσειρά. Το ίδιο ισχύει και για τον εντοπισμό. Αυτό δεν σημαίνει ότι δεν μπορεί να γίνει με την τυπική σύνταξη XSLT. Υπάρχουν τρόποι, αλλά δεν είναι τόσο εύκολο όσο θα θέλαμε. Εάν θέλετε πραγματικά να γράψετε συναρτήσεις χειρισμού κειμένου χρησιμοποιώντας αναδρομικά πρότυπα, γίνετε επισκέπτης μου.

Η κύρια αδυναμία του XSLT είναι η επεξεργασία κειμένου, η οποία φαίνεται λογική δεδομένου ότι σκοπός της είναι η απόδοση XML. Ωστόσο, επειδή το περιεχόμενο XML είναι εξ ολοκλήρου κείμενο, το XSLT χρειάζεται ισχυρότερο χειρισμό κειμένου. Περιττό να πούμε, οι σχεδιαστές φύλλων στυλ απαιτούν κάποια δυνατότητα επέκτασης από καιρό σε καιρό. Με το Xalan, η Java παρέχει αυτήν την επεκτασιμότητα.

Χρησιμοποιήστε τάξεις JDK εντός του XSLT

Ίσως να είστε ευχαριστημένοι που γνωρίζετε ότι δεν χρειάζεται να γράψετε κώδικα Java για να επωφεληθείτε από την επεκτασιμότητα του Xalan. Όταν χρησιμοποιείτε το Xalan, μπορείτε να δημιουργήσετε και να καλέσετε μεθόδους σε σχεδόν οποιοδήποτε αντικείμενο Java. Πριν χρησιμοποιήσετε μια κλάση Java, πρέπει να δώσετε ένα XSLT χώρος ονομάτων γι 'αυτό. Αυτό το παράδειγμα δηλώνει "Ιάβα" ως χώρος ονομάτων για οτιδήποτε μέσα ή κάτω από το πακέτο Java (δηλαδή, ολόκληρο το JDK):

Τώρα χρειαζόμαστε κάτι να κάνουμε. Ας ξεκινήσουμε με ένα μικρό έγγραφο XML:

 Το Java May Be Fad J. Burke 11/30/97 

Σας ζητήθηκε να διαμορφώσετε αυτό το XML, ώστε ο τίτλος να εμφανίζεται με κεφαλαία γράμματα. Ένας προγραμματιστής νέος στο XSLT θα ανοίξει απλώς μια αναφορά XSLT για να αναζητήσει προς Άνω () λειτουργία; Ωστόσο, θα ήταν απογοητευμένη όταν διαπίστωσε ότι δεν υπάρχει αναφορά. ο μεταφράζω() η μέθοδος είναι το καλύτερο στοίχημά σας, αλλά έχω μια ακόμη καλύτερη μέθοδο: java.lang.String.toUpperCase (). Για να χρησιμοποιήσετε αυτήν τη μέθοδο, πρέπει να δημιουργήσετε ένα Σειρά αντικείμενο με τα περιεχόμενα του τίτλου. Δείτε πώς μπορείτε να δημιουργήσετε ένα νέο Σειρά παρουσία με τα περιεχόμενα του στοιχείου τίτλου:

ο όνομα Το χαρακτηριστικό καθορίζει τη λαβή στο νέο σας Σειρά παράδειγμα. Επικαλέσατε τον κατασκευαστή καθορίζοντας πρώτα το χώρο ονομάτων μαζί με την υπόλοιπη διαδρομή προς το Σειρά τάξη. Όπως ίσως έχετε παρατηρήσει, Σειρά στερείται α νέος() μέθοδος. Εσυ χρησιμοποιεις νέος() να κατασκευάσει ένα αντικείμενο Java στο Xalan? αντιστοιχεί σε Java νέος λέξη-κλειδί. Τα επιχειρήματα που δόθηκαν στο νέος() καθορίστε την έκδοση του κατασκευαστή που θα κληθεί. Τώρα που έχετε τα περιεχόμενα του τίτλου σε μια Java Σειρά αντικείμενο, μπορείτε να χρησιμοποιήσετε το σεUpperCase () μέθοδος, όπως έτσι:

Αυτό μπορεί να σας φαίνεται παράξενο στην αρχή. Όταν χρησιμοποιείτε μεθόδους Java σε μια συγκεκριμένη παρουσία, το πρώτο όρισμα είναι η παρουσία στην οποία θέλετε να γίνει επίκληση της μεθόδου. Προφανώς ο Xalan χρησιμοποιεί ενδοσκόπηση για να παρέχει αυτή την ικανότητα.

Παρακάτω θα βρείτε ένα άλλο κόλπο. Δείτε πώς μπορείτε να εκπέμψετε την ημερομηνία και την ώρα οπουδήποτε μέσα στο φύλλο στυλ σας χρησιμοποιώντας java.lang. Ημερομηνία:

Εδώ είναι κάτι που θα κάνει την ημέρα όποιον απαιτείται να εντοπίσει ένα γενικό φύλλο στυλ μεταξύ δύο ή περισσότερων γλωσσών. Μπορείς να χρησιμοποιήσεις java.util.ResourceBundle για να εντοπίσετε το κυριολεκτικό κείμενο σε ένα φύλλο στυλ. Επειδή η XML σας έχει ετικέτα συγγραφέα, ίσως θέλετε να εκτυπώσετε "Συντάκτης:" δίπλα στο όνομα του ατόμου.

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

Αντί να αντιγράψετε το φύλλο στυλ για κάθε γλώσσα, μπορείτε να επωφεληθείτε από τις δυνατότητες εντοπισμού της Java. Εντοπισμός με τη βοήθεια ενός Πακέτο πόρων αποδεικνύει μια καλύτερη προσέγγιση. Μέσα στο XSLT, φορτώστε το Πακέτο πόρων στην αρχή των φύλλων στυλ σας, όπως:

ο Πακέτο πόρων τάξη αναμένει να βρει ένα αρχείο που ονομάζεται Γενικά. Ακίνητα στο δικό σας CLASSPATH. Μόλις δημιουργηθεί το πακέτο, μπορεί να επαναχρησιμοποιηθεί σε όλο το φύλλο στυλ. Αυτό το παράδειγμα ανακτά το συντάκτης πόρος:

Παρατηρήστε ξανά την παράξενη υπογραφή μεθόδου. Κανονικά, ResourceBundle.getString () παίρνει μόνο ένα επιχείρημα. Ωστόσο, στο XSLT πρέπει επίσης να καθορίσετε το αντικείμενο με το οποίο θέλετε να επικαλεστείτε τη μέθοδο.

Γράψτε τις δικές σας επεκτάσεις

Για ορισμένες σπάνιες καταστάσεις, ίσως χρειαστεί να γράψετε τη δική σας επέκταση XSLT, με τη μορφή είτε μιας επέκτασης είτε ενός στοιχείου επέκτασης. Θα συζητήσω τη δημιουργία μιας λειτουργίας επέκτασης, μιας έννοιας που είναι αρκετά εύκολο να κατανοηθεί. Οποιαδήποτε λειτουργία επέκτασης Xalan μπορεί να λάβει συμβολοσειρές ως συμβολοσειρές εισόδου και επιστροφής στον επεξεργαστή XSLT. Οι επεκτάσεις σας μπορούν επίσης να λάβουν NodeLists ή Κόμβοςως επιχειρήματα και επιστρέψτε αυτούς τους τύπους στον επεξεργαστή XSLT. Χρησιμοποιώντας Κόμβοςs ή NodeLists σημαίνει ότι μπορείτε να προσθέσετε στο αρχικό έγγραφο XML με μια λειτουργία επέκτασης, κάτι που θα κάνουμε.

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

Παρασκευή, 30 Νοεμβρίου 200

Μπορεί το πρότυπο XSLT να ολοκληρώσει την παραπάνω ημερομηνία; Το XSLT μπορεί να ολοκληρώσει το μεγαλύτερο μέρος της εργασίας. Ο καθορισμός της πραγματικής ημέρας είναι το δύσκολο κομμάτι. Ένας τρόπος για να λύσετε γρήγορα αυτό το πρόβλημα είναι να χρησιμοποιήσετε το java.text.SimpleDate μορφή κλάσης σε μια συνάρτηση επέκτασης για να επιστρέψει μια συμβολοσειρά μορφοποιημένη όπως θέλουμε. Αλλά περιμένετε: παρατηρήστε ότι η ημέρα εμφανίζεται με έντονο κείμενο. Αυτό μας επιστρέφει στο αρχικό πρόβλημα. Ο λόγος που εξετάζουμε ακόμη και μια συνάρτηση επέκτασης είναι επειδή το αρχικό έγγραφο XML απέτυχε να διαμορφώσει την ημερομηνία ως ομάδα κόμβων. Εάν η συνάρτηση επέκτασης επιστρέψει μια συμβολοσειρά, θα το κάνουμε ακόμη δυσκολεύεστε να διαμορφώσετε το πεδίο της ημέρας διαφορετικά από το υπόλοιπο της συμβολοσειράς ημερομηνίας. Ακολουθεί μια πιο χρήσιμη μορφή, τουλάχιστον από την άποψη ενός σχεδιαστή XSLT:

  11 30 2001  

Τώρα δημιουργούμε μια συνάρτηση επέκτασης XSLT, παίρνοντας μια συμβολοσειρά ως όρισμα και επιστρέφουμε έναν κόμβο XML σε αυτήν τη μορφή:

  30 Νοεμβρίου Παρασκευή 2001 

Η τάξη που φιλοξενεί τη λειτουργία επέκτασής μας δεν εφαρμόζει ούτε επεκτείνει τίποτα. θα καλέσουμε την τάξη DateFormatter:

δημόσια τάξη DateFormatter {δημόσια στατική μορφή κόμβου (ημερομηνία συμβολοσειράς) {} 

Πω πω, πολύ εύκολο, ε; Δεν υπάρχουν απολύτως απαιτήσεις σχετικά με τον τύπο ή τη διεπαφή μιας λειτουργίας επέκτασης Xalan. Γενικά, οι περισσότερες λειτουργίες επέκτασης θα διαρκέσουν Σειρά ως επιχείρημα και επιστρέψτε ένα άλλο Σειρά. Άλλα κοινά μοτίβα είναι η αποστολή ή η λήψη org.w3c.dom.NodeListή άτομο Κόμβοςαπό μια λειτουργία επέκτασης, όπως θα κάνουμε. Ανατρέξτε στην τεκμηρίωση Xalan για λεπτομέρειες σχετικά με τον τρόπο μετατροπής των τύπων Java σε τύπους XSLT.

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

 Document doc = DocumentBuilderFactory.newInstance (). newDocumentBuilder (). newDocument (); Στοιχείο dateNode = doc.createElement ("formatted-date"); SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance (DateFormat.SHORT, τοπικές ρυθμίσεις); df.setLenient (true); Ημερομηνία d = df.parse (ημερομηνία); df.applyPattern ("MMMM"); addChild (dateNode, "μήνας", df.format (d)); df.applyPattern ("EEEE"); addChild (dateNode, "ημέρα της εβδομάδας", df.format (d)); df.applyPattern ("εεεε"); dateNode.setAttribute ("έτος", df.format (d)); ημερομηνία επιστροφής Κόμβος; 

dateNode θα περιέχει τις μορφοποιημένες τιμές ημερομηνίας που επιστρέφουμε στο φύλλο στυλ. Παρατηρήστε ότι έχουμε χρησιμοποιήσει java.text.SimpleDateFormat () για ανάλυση της ημερομηνίας. Αυτό μας επιτρέπει να επωφεληθούμε πλήρως από την υποστήριξη ημερομηνιών της Java, συμπεριλαμβανομένων των δυνατοτήτων εντοπισμού της. SimpleDateFormat χειρίζεται την αριθμητική μετατροπή ημερομηνίας και επιστρέφει ονόματα μήνα και ημέρας που ταιριάζουν με τις τοπικές ρυθμίσεις του VM που εκτελεί την εφαρμογή μας.

Θυμηθείτε: ο πρωταρχικός σκοπός μιας λειτουργίας επέκτασης είναι απλώς να μας επιτρέψει την πρόσβαση σε υπάρχουσες λειτουργίες Java γράψτε όσο το δυνατόν λιγότερο κώδικα. Μια συνάρτηση επέκτασης, όπως οποιαδήποτε μέθοδος Java, μπορεί να χρησιμοποιήσει άλλες μεθόδους στην ίδια τάξη. Για απλοποίηση του μορφή() υλοποίηση, μετακόμισα τον επαναλαμβανόμενο κώδικα σε μια μικρή μέθοδο χρησιμότητας:

private void addChild (Γονικός κόμβος, όνομα συμβολοσειράς, κείμενο συμβολοσειράς) {Element child = parent.getOwnerDocument (). createElement (name); child.appendChild (parent.getOwnerDocument (). createTextNode (κείμενο)); parent.appendChild (παιδί); } 

Χρησιμοποιήστε το DateFormatter σε ένα φύλλο στυλ

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

Αυτή τη φορά, προκριθήκαμε πλήρως τη διαδρομή προς την τάξη που φιλοξενεί τη λειτουργία επέκτασης. Αυτό είναι προαιρετικό και εξαρτάται από το αν θα χρησιμοποιείτε άλλες τάξεις εντός του ίδιου πακέτου ή μόνο ένα αντικείμενο επέκτασης. Μπορείτε να δηλώσετε το πλήρες CLASSPATH ως χώρο ονομάτων ή χρησιμοποιήστε ένα πακέτο και καθορίστε την κλάση στην οποία ενεργοποιείται η συνάρτηση επέκτασης. Καθορίζοντας το πλήρες CLASSPATH, πληκτρολογούμε λιγότερο όταν καλούμε τη συνάρτηση.

Για να χρησιμοποιήσετε τη συνάρτηση, απλώς καλέστε την από μέσα επιλέγω ετικέτα, όπως έτσι: