Ανάλυση δεδομένων XML. Ανάλυση δεδομένων XML Δημιουργία αναλυτής


Συγγραφέας: Arseny Kapoulkine
Ημερομηνία δημοσίευσης: 21 Σεπτεμβρίου 2012
Μετάφραση: A. Panin
Ημερομηνία μετάφρασης: 10 Νοεμβρίου 2013

Εισαγωγή

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

Αυτό το κεφάλαιο περιγράφει διάφορες τεχνικές που στοχεύουν στη βελτίωση της απόδοσης του περιγραφόμενου συστήματος ανάλυσης και επιτρέπουν στον συγγραφέα να αναπτύξει ένα εξαιρετικά παραγωγικό σύστημα ανάλυσης χρησιμοποιώντας τη γλώσσα προγραμματισμού C++: pugixml. Αν και αυτές οι τεχνικές χρησιμοποιήθηκαν για το σύστημα ανάλυσης εγγράφων XML, οι περισσότερες από αυτές μπορούν να εφαρμοστούν σε συστήματα ανάλυσης εγγράφων άλλων μορφών ή ακόμα και σε εντελώς άσχετα στοιχεία λογισμικού (για παράδειγμα, οι αλγόριθμοι διαχείρισης μνήμης χρησιμοποιούνται ευρέως σε άσχετα συστήματα ανάλυσης έγγραφα κειμένουπεριοχές).

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

Μοντέλα συστημάτων ανάλυσης XML

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

  • Όταν χρησιμοποιείτε συστήματα ανάλυσης που βασίζονται σε SAX (Simple API για XML), ο χρήστης λαμβάνει στην τοποθεσία του στοιχείο λογισμικού, το οποίο αναμένει μια ροή δεδομένων εγγράφου ως είσοδο και παρέχει πολλές λειτουργίες επανάκλησης όπως "άνοιγμα ετικέτας", "κλείσιμο ετικέτας", "χαρακτήρας μέσα στην ετικέτα". Το σύστημα ανάλυσης χρησιμοποιεί λειτουργίες επανάκλησης κατά την επεξεργασία δεδομένων εγγράφου. Το περιβάλλον που απαιτείται για την ανάλυση περιορίζεται από το βάθος του δέντρου του τρέχοντος στοιχείου, το οποίο συνεπάγεται σημαντική μείωση στις απαιτήσεις μνήμης. Αυτός ο τύπος συστήματος ανάλυσης μπορεί να χρησιμοποιηθεί για την επεξεργασία εγγράφων ροής όταν μόνο ένα τμήμα του εγγράφου είναι διαθέσιμο κάθε φορά.
  • Η ανάλυση έλξης είναι παρόμοια με την ανάλυση που βασίζεται σε SAX όσον αφορά την ίδια τη διαδικασία - ένα στοιχείο εγγράφου υποβάλλεται σε επεξεργασία κάθε φορά, αλλά η μέθοδος διαχείρισης της διαδικασίας ανάλυσης έχει αλλάξει: σε ένα σύστημα ανάλυσης που βασίζεται σε SAX, η διαδικασία ανάλυσης ελέγχεται από το ίδιο το σύστημα χρησιμοποιεί λειτουργίες επανάκλησης, ενώ ενώ βρίσκεται σε ανάλυση έλξης, ο χρήστης ελέγχει τη διαδικασία ανάλυσης χρησιμοποιώντας ένα αντικείμενο που μοιάζει με επαναλήπτη.
  • Όταν χρησιμοποιεί συστήματα ανάλυσης που βασίζονται σε DOM (Μοντέλο αντικειμένου εγγράφου), ο χρήστης μεταβιβάζει στο σύστημα ανάλυσης ένα πλήρες έγγραφο με τη μορφή προσωρινής μνήμης ή ροής δεδομένων κειμένου, βάσει του οποίου το σύστημα ανάλυσης δημιουργεί μια αναπαράσταση αντικειμένου στη μνήμη ολόκληρου του δέντρο στοιχείων εγγράφου, χρησιμοποιώντας ξεχωριστά αντικείμενα για κάθε ένα συγκεκριμένο στοιχείο ή Χαρακτηριστικό XML, καθώς και ένα σύνολο έγκυρων λειτουργιών (για παράδειγμα, "get all παιδικά στοιχείααυτός ο κόμβος"). Η βιβλιοθήκη pugxml χρησιμοποιεί αυτό το μοντέλο.

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

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

Αρχιτεκτονικές λύσεις σε pugixml

Κατά την ανάπτυξη της βιβλιοθήκης pugixml, μεγάλο μέρος της εστίασης ήταν στο πρόβλημα της δημιουργίας της αναπαράστασης DOM, καθώς παρόλο που ήταν διαθέσιμα γρήγορα και ελαφριά συστήματα ανάλυσης που βασίζονταν σε SAX (όπως το Expat), όλα τα συστήματα ανάλυσης XML που βασίζονταν σε DOM ήταν διαθέσιμα για παραγωγή χρήση τη στιγμή που δημιουργήθηκε το pugixml (2006) ήταν είτε όχι πολύ ελαφρύ είτε όχι πολύ γρήγορο. Με βάση αυτό, ο κύριος στόχος της διαδικασίας ανάπτυξης puixml είναι η δημιουργία μιας πολύ γρήγορης, ελαφριάς βιβλιοθήκης για την εκτέλεση χειρισμού εγγράφων XML βάσει DOM.


Η δημοσίευση αυτού του άρθρου επιτρέπεται μόνο με σύνδεσμο στον ιστότοπο του συγγραφέα του άρθρου

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

Κατά την ανάλυση μεγάλων αρχείων XML, προκύπτουν δύο προβλήματα:
1. Δεν υπάρχει αρκετή μνήμη.
2. Δεν υπάρχει αρκετός χρόνος για την εκτέλεση του σεναρίου.

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

Η PHP έχει πολλές ενσωματωμένες επιλογές επεξεργασίας XML - SimpleXML, DOM, SAX.
Όλες αυτές οι επιλογές περιγράφονται λεπτομερώς σε πολλά άρθρα με παραδείγματα, αλλά όλα τα παραδείγματα δείχνουν την εργασία με ένα πλήρες έγγραφο XML.

Εδώ είναι ένα παράδειγμα, από το οποίο παίρνουμε ένα αντικείμενο αρχείο XML

Τώρα μπορείτε να επεξεργαστείτε αυτό το αντικείμενο, ΑΛΛΑ...
Όπως μπορείτε να δείτε, ολόκληρο το αρχείο XML διαβάζεται στη μνήμη και, στη συνέχεια, όλα αναλύονται σε ένα αντικείμενο.
Δηλαδή, όλα τα δεδομένα πηγαίνουν στη μνήμη και αν δεν υπάρχει αρκετή εκχωρημένη μνήμη, το σενάριο σταματά.

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

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

Συνάρτηση webi_xml ($file)
{

########
### συνάρτηση δεδομένων

{
εκτύπωση $data ;
}
############################################



{
εκτύπωση $name ;
print_r($attrs);
}


## λειτουργία ετικέτας κλεισίματος
συνάρτηση endElement ($parser, $name)
{
εκτύπωση $name ;
}
############################################

($xml_parser, "data");

// ανοίξτε το αρχείο
$fp = fopen($file, "r");

$perviy_vxod = 1 ; $data = " " ;



{

$simvol = fgetc ($fp); $data .= $simvol ;


if($simvol != ">" ) (συνέχεια;)


ηχώ "

Διακοπή;
}

$data = " " ;
}
fclose($fp);

Webi_xml("1.xml");

?>

Σε αυτό το παράδειγμα, έβαλα τα πάντα σε μια συνάρτηση webi_xml() και στο κάτω μέρος μπορείτε να δείτε την κλήση της.
Το ίδιο το σενάριο αποτελείται από τρεις κύριες λειτουργίες:
1. Μια συνάρτηση που πιάνει το άνοιγμα της ετικέτας startElement().
2. Μια συνάρτηση που πιάνει την ετικέτα κλεισίματος endElement().
3. Και η συνάρτηση λήψης δεδομένων data() .

Ας υποθέσουμε ότι τα περιεχόμενα του αρχείου 1.xml είναι μια συνταγή



< title >Απλό ψωμί
< ingredient amount = "3" unit = "стакан" >Αλεύρι
< ingredient amount = "0.25" unit = "грамм" >Μαγιά
< ingredient amount = "1.5" unit = "стакан" >Ζεστό νερό
< ingredient amount = "1" unit = "чайная ложка" >Αλας
< instructions >
< step > Ανακατεύουμε όλα τα υλικά και ζυμώνουμε καλά.
< step > Σκεπάζουμε με ένα πανί και αφήνουμε για μία ώρα σε ζεστό δωμάτιο..
< step > Ξαναζυμώνουμε, τοποθετήστε σε ένα ταψί και βάλτε το στο φούρνο.
< step > Επισκεφθείτε τον ιστότοπο του ιστότοπου


Ξεκινάμε τα πάντα καλώντας τη γενική συνάρτηση webi_xml ("1.xml" );
Στη συνέχεια, ο αναλυτής ξεκινά σε αυτή τη συνάρτηση και μετατρέπει όλα τα ονόματα των ετικετών σε κεφαλαία, έτσι ώστε όλες οι ετικέτες να έχουν την ίδια πεζή και κεφαλαία.

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);

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

xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "data");

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

Και στείλτε το στον αποσυναρμολογητή
xml_parse ($xml_parser, $data, feof ($fp));
Μετά την επεξεργασία των δεδομένων, η μεταβλητή συμβολοσειράς επαναφέρεται και η συλλογή δεδομένων σε μια συμβολοσειρά ξεκινά ξανά και η συμβολοσειρά σχηματίζεται για δεύτερη φορά

Στην τρίτη
</b><br>στο τέταρτο <br><b>Απλό ψωμί

Λάβετε υπόψη ότι μια μεταβλητή συμβολοσειράς σχηματίζεται πάντα από μια ολοκληρωμένη ετικέτα > και δεν είναι απαραίτητο να στείλετε στον διαρρήκτη μια ανοιχτή και κλειστή ετικέτα με δεδομένα, για παράδειγμα
Απλό ψωμί
Είναι σημαντικό για αυτόν τον χειριστή να λάβει μια ολόκληρη αδιάσπαστη ετικέτα, τουλάχιστον μια ανοιχτή ετικέτα και στο επόμενο βήμα μια κλειστή ετικέτα ή να λάβει αμέσως 1000 γραμμές ενός αρχείου, δεν πειράζει, το κύριο πράγμα είναι ότι η ετικέτα δεν σπάει, για παράδειγμα

le>Σκέτο ψωμί
Με αυτόν τον τρόπο, είναι αδύνατη η αποστολή δεδομένων στον χειριστή, καθώς η ετικέτα είναι σχισμένη.
Μπορείτε να βρείτε τη δική σας μέθοδο αποστολής δεδομένων στον χειριστή, για παράδειγμα, να συλλέξετε 1 megabyte δεδομένων και να τα στείλετε στον χειριστή για να αυξήσετε την ταχύτητα, απλώς βεβαιωθείτε ότι οι ετικέτες είναι πάντα συμπληρωμένες και τα δεδομένα μπορούν να σχιστούν
Απλός</b><br><b>ψωμί

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

Τώρα ας δούμε πώς γίνεται η επεξεργασία αυτών των δεδομένων και πώς να τα αποκτήσετε.

Ας ξεκινήσουμε με τη λειτουργία ανοίγματος ετικετών startElement ($parser, $name, $attrs)
Ας υποθέσουμε ότι η επεξεργασία έχει φτάσει στη γραμμή
< ingredient amount = "3" unit = "стакан" >Αλεύρι
Τότε μέσα στη συνάρτηση η μεταβλητή $name θα είναι ίση με συστατικόδηλαδή το όνομα της ανοιχτής ετικέτας (δεν έχει φτάσει ακόμα να κλείσει η ετικέτα).
Επίσης σε αυτήν την περίπτωση, θα είναι διαθέσιμος ένας πίνακας χαρακτηριστικών αυτής της ετικέτας $attrs, ο οποίος θα περιέχει δεδομένα ποσό = "3" και μονάδα = "γυαλί".

Μετά από αυτό, τα δεδομένα της ανοιχτής ετικέτας υποβλήθηκαν σε επεξεργασία από τη συνάρτηση δεδομένα ($parser, $data)
Η μεταβλητή $data θα περιέχει όλα όσα βρίσκονται μεταξύ των ετικετών ανοίγματος και κλεισίματος, στην περίπτωσή μας αυτό είναι το κείμενο Muka

Και η επεξεργασία της συμβολοσειράς μας από τη συνάρτηση τελειώνει endElement ($parser, $name)
Αυτό είναι το όνομα της κλειστής ετικέτας, στην περίπτωσή μας το $name θα είναι ίσο με συστατικό

Και μετά όλα έκαναν πάλι κύκλους.

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

Συνάρτηση webi_xml ($file)
{
παγκόσμια $webi_depth ; // μετρητής για παρακολούθηση του βάθους ένθεσης
$webi_depth = 0 ;
καθολική $webi_tag_open ; // θα περιέχει μια σειρά από open in αυτή τη στιγμήετικέτες
$webi_tag_open = array();
καθολική $webi_data_temp ; // αυτός ο πίνακας θα περιέχει τα δεδομένα μιας ετικέτας

####################################################
### συνάρτηση δεδομένων
δεδομένα συνάρτησης ($parser, $data)
{
παγκόσμια $webi_depth ;
καθολική $webi_tag_open ;
καθολική $webi_data_temp ;
// προσθέστε δεδομένα στον πίνακα που υποδεικνύει ένθεση και ανοιχτή ετικέτα
$webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "data" ].= $data ;
}
############################################

####################################################
### συνάρτηση ανοίγματος ετικέτας
συνάρτηση startElement ($parser, $name, $attrs)
{
παγκόσμια $webi_depth ;
καθολική $webi_tag_open ;
καθολική $webi_data_temp ;

// εάν το επίπεδο ένθεσης δεν είναι πλέον μηδέν, τότε μια ετικέτα είναι ήδη ανοιχτή
// και τα δεδομένα από αυτό είναι ήδη στον πίνακα, μπορείτε να τα επεξεργαστείτε
εάν ($webi_depth)
{




" ;

Τυπώνω "
" ;
print_r($webi_tag_open); // πίνακας ανοιχτών ετικετών
Τυπώνω "


" ;

// μετά την επεξεργασία των δεδομένων, διαγράψτε τα για να ελευθερώσετε μνήμη
unset($GLOBALS [ "webi_data_temp" ][$webi_depth ]);
}

// τώρα ανοίγει η επόμενη ετικέτα και θα γίνει περαιτέρω επεξεργασία στο επόμενο βήμα
$webi_depth++; // αύξηση φωλιάσματος

$webi_tag_open [ $webi_depth ]= $name ; // προσθέστε μια ανοιχτή ετικέτα στον πίνακα πληροφοριών
$webi_data_temp [ $webi_depth ][ $name ][ "attrs" ]= $attrs ; // τώρα προσθέστε χαρακτηριστικά ετικέτας

}
###############################################

#################################################
## λειτουργία ετικέτας κλεισίματος
συνάρτηση endElement ($parser, $name) (
παγκόσμια $webi_depth ;
καθολική $webi_tag_open ;
καθολική $webi_data_temp ;

// Η επεξεργασία δεδομένων ξεκινά εδώ, για παράδειγμα προσθήκη στη βάση δεδομένων, αποθήκευση σε αρχείο κ.λπ.
// Το $webi_tag_open περιέχει μια αλυσίδα ανοιχτών ετικετών ανά επίπεδο ένθεσης
// για παράδειγμα το $webi_tag_open[$webi_depth] περιέχει το όνομα της ανοιχτής ετικέτας της οποίας οι πληροφορίες επεξεργάζονται αυτήν τη στιγμή
// Επίπεδο ένθεσης ετικέτας $webi_depth
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]]["attrs"] πίνακας χαρακτηριστικών ετικετών
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]]["data"] δεδομένα ετικέτας

Εκτύπωση "δεδομένων". $webi_tag_open [ $webi_depth ]. "--" .($webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "data" ]). "
" ;
print_r ($webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "attrs" ]);
Τυπώνω "
" ;
print_r($webi_tag_open);
Τυπώνω "


" ;

Unset($GLOBALS [ "webi_data_temp" ]); // μετά την επεξεργασία των δεδομένων, διαγράφουμε ολόκληρο τον πίνακα με τα δεδομένα, αφού η ετικέτα ήταν κλειστή
unset($GLOBALS [ "webi_tag_open" ][$webi_depth ]); // διαγράψτε πληροφορίες σχετικά με αυτήν την ανοιχτή ετικέτα... αφού έκλεισε

$webi_depth --; // μείωση φωλιάς
}
############################################

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);

// υποδεικνύει ποιες λειτουργίες θα λειτουργούν κατά το άνοιγμα και το κλείσιμο ετικετών
xml_set_element_handler($xml_parser, "startElement", "endElement");

// καθορίστε μια συνάρτηση για εργασία με δεδομένα
xml_set_character_data_handler($xml_parser, "data");

// ανοίξτε το αρχείο
$fp = fopen($file, "r");

$perviy_vxod = 1 ; // επισημάνετε για να ελέγξετε την πρώτη καταχώρηση στο αρχείο
$data = " " ; // εδώ συλλέγουμε δεδομένα από το αρχείο σε μέρη και τα στέλνουμε στον αναλυτή xml

// βρόχο μέχρι να βρεθεί το τέλος του αρχείου
ενώ (! feof ($fp ) και $fp )
{
$simvol = fgetc ($fp); // διαβάστε έναν χαρακτήρα από το αρχείο
$data .= $simvol ; // προσθέστε αυτόν τον χαρακτήρα στα δεδομένα που θα σταλούν

// εάν ο χαρακτήρας δεν είναι η ετικέτα τέλους, τότε επιστρέψτε στην αρχή του βρόχου και προσθέστε έναν άλλο χαρακτήρα στα δεδομένα και ούτω καθεξής μέχρι να βρεθεί η ετικέτα τέλους
if($simvol != ">" ) (συνέχεια;)
// εάν βρέθηκε η ετικέτα κλεισίματος, τώρα θα στείλουμε αυτά τα συλλεγμένα δεδομένα για επεξεργασία

// ελέγξτε αν αυτή είναι η πρώτη καταχώρηση στο αρχείο, τότε θα διαγράψουμε όλα όσα βρίσκονται πριν από την ετικέτα// καθώς μερικές φορές μπορεί να συναντήσετε σκουπίδια πριν από την έναρξη του XML (αδέξια προγράμματα επεξεργασίας ή το αρχείο ελήφθη από ένα σενάριο από άλλο διακομιστή)
if($perviy_vxod ) ( $data = strstr ($data , "

// ρίξτε τώρα τα δεδομένα στον αναλυτή xml
if (! xml_parse ($xml_parser, $data, feof ($fp))) (

// εδώ μπορείτε να επεξεργαστείτε και να λάβετε σφάλματα εγκυρότητας...
// μόλις παρουσιαστεί ένα σφάλμα, η ανάλυση σταματά
ηχώ "
Σφάλμα XML: " . xml_error_string(xml_get_error_code($xml_parser));
ηχώ "στη γραμμή" . xml_get_current_line_number ($xml_parser);
Διακοπή;
}

// μετά την ανάλυση, απορρίψτε τα συλλεγμένα δεδομένα για το επόμενο βήμα του κύκλου.
$data = " " ;
}
fclose($fp);
xml_parser_free($xml_parser);
// αφαίρεση καθολικών μεταβλητών
unset($GLOBALS [ "webi_depth" ]);
unset($GLOBALS [ "webi_tag_open" ]);
unset($GLOBALS [ "webi_data_temp" ]);

Webi_xml("1.xml");

?>

Ολόκληρο το παράδειγμα συνοδεύεται από σχόλια, τώρα δοκιμή και πείραμα.
Λάβετε υπόψη ότι στη λειτουργία της εργασίας με δεδομένα, τα δεδομένα δεν εισάγονται απλώς σε έναν πίνακα, αλλά προστίθενται χρησιμοποιώντας το " .=" δεδομένου ότι τα δεδομένα ενδέχεται να μην φθάνουν στο σύνολό τους και αν κάνετε απλώς μια ανάθεση, τότε από καιρό σε καιρό θα λαμβάνετε τα δεδομένα σε κομμάτια.

Λοιπόν, αυτό είναι όλο, τώρα υπάρχει αρκετή μνήμη κατά την επεξεργασία ενός αρχείου οποιουδήποτε μεγέθους, αλλά ο χρόνος εκτέλεσης του σεναρίου μπορεί να αυξηθεί με διάφορους τρόπους.
Εισαγάγετε μια συνάρτηση στην αρχή του σεναρίου
set_time_limit(6000);
ή
ini_set ("max_execution_time" , "6000" );

Ή προσθέστε κείμενο στο αρχείο .htaccess
php_value max_execution_time 6000

Αυτά τα παραδείγματα θα αυξήσουν τον χρόνο εκτέλεσης του σεναρίου στα 6000 δευτερόλεπτα.
Μπορείτε να αυξήσετε τον χρόνο με αυτόν τον τρόπο μόνο όταν η ασφαλής λειτουργία είναι απενεργοποιημένη.

Εάν έχετε πρόσβαση στην επεξεργασία του php.ini, μπορείτε να αυξήσετε το χρόνο χρήσης
max_execution_time = 6000

Για παράδειγμα, στη φιλοξενία Masterhost, τη στιγμή της σύνταξης αυτού του άρθρου, η αύξηση του χρόνου σεναρίου απαγορεύεται, παρά λειτουργία ασφαλείας, αλλά αν είστε επαγγελματίας, μπορείτε να φτιάξετε τη δική σας έκδοση php σε masterhost, αλλά αυτό δεν περιλαμβάνεται σε αυτό το άρθρο.

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

Χρησιμοποιώντας την επέκταση SimpleXMLστην PHP, η οποία προστέθηκε ξανά στην PHP 5.0, η εργασία με XML είναι πολύ εύκολη και απλή. Σε αυτό το άρθρο θα σας δείξω πώς να το κάνετε.

Βασικά στοιχεία χρήσης

Ας ξεκινήσουμε με το παρακάτω παράδειγμα γλώσσες.xml:


>

> 1972>
> Ντένις Ρίτσι >
>

> 1995>
> Ράσμους Λέρντορφ >
>

> 1995>
> Τζέιμς Γκόσλινγκ >
>
>

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

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

Και οι δύο συναρτήσεις διαβάζουν ολόκληρο το δέντρο DOM στη μνήμη και επιστρέφουν ένα αντικείμενο SimpleXMLEστοιχείο. Στο παραπάνω παράδειγμα, το αντικείμενο αποθηκεύεται στη μεταβλητή $languages. Μπορείτε να χρησιμοποιήσετε τις λειτουργίες var_dump()ή print_r()για να λάβετε λεπτομέρειες σχετικά με το επιστρεφόμενο αντικείμενο εάν θέλετε.

Αντικείμενο SimpleXMLElement
[lang] => Πίνακας
[ 0 ] => Αντικείμενο SimpleXMLElement
[@attributes] => Πίνακας
[όνομα] => Γ
[εμφανίστηκε] => 1972
[δημιουργός] => Ντένις Ρίτσι
[ 1 ] => Αντικείμενο SimpleXMLElement
[@attributes] => Πίνακας
[όνομα] => PHP
[εμφανίστηκε] => 1995
[δημιουργός] => Rasmus Lerdorf
[ 2 ] => Αντικείμενο SimpleXMLElement
[@attributes] => Πίνακας
[όνομα] => Java
[εμφανίστηκε] => 1995
[δημιουργός] => Τζέιμς Γκόσλινγκ
)
)

Αυτό το XML περιέχει ένα ριζικό στοιχείο Γλώσσες, στο εσωτερικό του οποίου υπάρχουν τρία στοιχεία lang.Κάθε στοιχείο πίνακα αντιστοιχεί σε ένα στοιχείο langστο έγγραφο XML.

Μπορείτε να αποκτήσετε πρόσβαση στις ιδιότητες ενός αντικειμένου χρησιμοποιώντας τον τελεστή -> . Για παράδειγμα, το $languages->lang θα σας επιστρέψει ένα αντικείμενο SimpleXMLElement που ταιριάζει με το πρώτο στοιχείο lang. Αυτό το αντικείμενο περιέχει δύο ιδιότητες: εμφανίστηκε και δημιουργός.

$languages ​​-> lang [ 0 ] -> εμφανίστηκε ;
$languages ​​-> lang [ 0 ] -> creator ;

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

foreach ($languages ​​-> lang as $lang ) (
printf(
"" ,
$lang [ "όνομα" ] ,
εμφανίστηκε το $lang ->,
$lang -> δημιουργός
) ;
}

Παρατηρήστε πώς είχα πρόσβαση στο όνομα του χαρακτηριστικού lang του στοιχείου για να λάβω το όνομα της γλώσσας. Με αυτόν τον τρόπο μπορείτε να αποκτήσετε πρόσβαση σε οποιοδήποτε χαρακτηριστικό ενός στοιχείου που αναπαρίσταται ως αντικείμενο SimpleXMLElement.

Εργασία με Χώρους Ονομάτων

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



xmlns:dc =>

> 1972>
> Ντένις Ρίτσι >
>

> 1995>
> Ράσμους Λέρντορφ >
>

> 1995>
> Τζέιμς Γκόσλινγκ >
>
>

Τώρα το στοιχείο δημιουργόςταιριάζει στον χώρο ονομάτων dcπου οδηγεί στη διεύθυνση http://purl.org/dc/elements/1.1/. Εάν προσπαθήσετε να εκτυπώσετε τους δημιουργούς γλώσσας χρησιμοποιώντας τον προηγούμενο κώδικα, δεν θα λειτουργήσει. Για να διαβάσετε τους χώρους ονομάτων στοιχείων, πρέπει να χρησιμοποιήσετε μία από τις ακόλουθες προσεγγίσεις.

Η πρώτη προσέγγιση είναι η χρήση ονομάτων URI απευθείας στον κώδικα κατά την πρόσβαση στον χώρο ονομάτων στοιχείων. Το παρακάτω παράδειγμα δείχνει πώς γίνεται αυτό:

$dc = $languages‎ -> lang [ 1 ] - > παιδιά( "http://purl.org/dc/elements/1.1/") ;
echo $dc -> creator ;

Μέθοδος παιδιά()παίρνει έναν χώρο ονομάτων και επιστρέφει θυγατρικά στοιχεία που ξεκινούν με ένα πρόθεμα. Χρειάζονται δύο ορίσματα, το πρώτο από τα οποία είναι ο χώρος ονομάτων XML και το δεύτερο είναι ένα προαιρετικό όρισμα το οποίο έχει ως προεπιλογή ψευδής. Εάν το δεύτερο όρισμα οριστεί σε TRUE, ο χώρος ονομάτων θα αντιμετωπίζεται ως πρόθεμα. Εάν FALSE, τότε ο χώρος ονομάτων θα αντιμετωπίζεται ως χώρος ονομάτων URL.

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

$namespaces = $languages‎ -> getNamespaces (true) ;
$dc = $languages ​​-> lang [ 1 ] -> παιδιά ( ($namespace [ "dc" ] );

echo $dc -> creator ;

Μέθοδος GetNamespaces()επιστρέφει μια σειρά ονομάτων προθεμάτων και τα συσχετισμένα URI τους. Δέχεται μια πρόσθετη παράμετρο η οποία είναι προεπιλεγμένη ψευδής. Αν το ρυθμίσετε όπως αληθής, τότε αυτή η μέθοδος θα επιστρέψει τα ονόματα που χρησιμοποιούνται στους κόμβους γονέα και θυγατρικού. Διαφορετικά, βρίσκει χώρους ονομάτων που χρησιμοποιούνται μόνο στον γονικό κόμβο.

Τώρα μπορείτε να επαναλάβετε τη λίστα των γλωσσών όπως αυτή:

$languages ​​= simplexml_load_file ("languages.xml" );
$ns = $languages‎ -> getNamespaces (true ) ;

foreach ($languages ​​-> lang as $lang ) (
$dc = $lang -> παιδιά ($ns [ "dc" ] ;
printf(
"

Το %s εμφανίστηκε στο %d και δημιουργήθηκε από το %s .

" ,
$lang [ "όνομα" ] ,
εμφανίστηκε το $lang ->,
$dc -> δημιουργός
) ;
}

Πρακτικό παράδειγμα - Ανάλυση καναλιού βίντεο από το YouTube

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

http://gdata.youtube.com/feeds/api/users/xxx/uploads

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

  • Σύνδεσμος στο βίντεο
  • Μικρογραφία
  • Ονομα

Θα ξεκινήσουμε αναζητώντας και φορτώνοντας το XML:

$channel = "Όνομα_καναλιού" ;
$url = "http://gdata.youtube.com/feeds/api/users/". $κανάλι. "/uploads" ;
$xml = file_get_contents($url);

$feed = simplexml_load_string ($xml) ;
$ns = $feed -> getNameSpaces ( true ) ;

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

>

>



Τίτλος… >

>

>

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

foreach ($feed -> καταχώρηση ως $entry ) (
$group = $entry -> παιδιά ($ns [ "μέσα" ] ;
$group = $group -> group ;
$thumbnail_attrs = $group -> thumbnail [ 1 ] -> χαρακτηριστικά () ;
$image = $thumbnail_attrs [ "url" ] ;
$player = $group -> player -> χαρακτηριστικά () ;
$link = $player [ "url" ] ;
$title = $group -> title ;
printf( "

" ,
$player, $image, $title);
}

συμπέρασμα

Τώρα που ξέρετε πώς να το χρησιμοποιήσετε SimpleXMLΓια την ανάλυση δεδομένων XML, μπορείτε να βελτιώσετε τις δεξιότητές σας αναλύοντας διαφορετικές ροές XML με διαφορετικά API. Ωστόσο, είναι σημαντικό να λάβετε υπόψη ότι το SimpleXML διαβάζει ολόκληρο το DOM στη μνήμη, επομένως, εάν αναλύετε ένα μεγάλο σύνολο δεδομένων, μπορεί να εξαντληθεί η μνήμη. Για να μάθετε περισσότερα σχετικά με το SimpleXML, διαβάστε την τεκμηρίωση.


Εάν έχετε οποιεσδήποτε ερωτήσεις, συνιστούμε να χρησιμοποιήσετε το δικό μας