Πολλές διαδικτυακές εφαρμογές ανταλλάσσουν δεδομένα σε μορφή XML. Εάν λάβουμε τέτοιου τύπου δεδομένα, μπορούμε να τα επεξεργαστούμε χρησιμοποιώντας parsers δύο κατηγοριών:
Η πρώτη κατηγορία parsers μπορεί να χρησιμοποιηθεί όταν ξέρουμε το μέγεθος του αρχείου που θα λάβουμε και είναι (σχετικά) περιορισμένο. Για αρχεία άγνωστου μεγέθους ή αρχεία που έρχονται τμηματικά, η δεύτερη κατηγορία είναι πιο ενδεδειγμένη.
Στο παράδειγμά μας, λαμβάνουμε μια βιβλιογραφική εγγραφή για ένα δεδομένο ISBN. Το ζητούμενο είναι να αναγνωρίσουμε σε ποια θεματική κατηγορία ανήκει το αντικείμενο με το ISBN αυτό. Η εγγραφή είναι μικρή σε μέγεθος και ζητάμε κάτι συγκεκριμένο, οπότε μπορούμε να χρησιμοποιήσουμε έναν ελαφρύ DOM-like parser που περιλαμβάνεται στη στάνταρ βιβλιοθήκη της Python: το ElementTree module
import xml.etree.ElementTree as ET
Το module ElementTree διαθέτει τη συνάρτηση parse(fileobj), η οποία μετατρέπει το περιεχόμενο ενός αρχείου σε δενδρική δομή:
# let's build an elementtree element now
tree = ET.parse(page)
Στη συνέχεια μπορούμε να αναζητήσουμε ορισμένους κόμβους στο δέντρο, δίνοντας το μονοπάτι (path) προς τους κόμβους αυτούς, ξεκινώντας από τη ρίζα.
# mark our namespaces for clarity
NS = "{http://www.loc.gov/MARC21/slim}" # the default namespace
ZSNS = "{http://www.loc.gov/zing/srw/}"
# find all nodes in the path zs:records/zs:record/zs:recordData/record/datafield under root
# NOTE: root tag is not listed in path as it is represented by 'tree' variable.
elm = tree.findall(ZSNS+"records/"+ZSNS+"record/"+ZSNS+"recordData/"+NS+"record/"+NS+"datafield")
Η findall() επιστρέφει μια λίστα κόμβων που ταιριάζουν στο μονοπάτι αναζήτησης. Στη συνέχεια διασχίζουμε τη λίστα αυτή, αναζητώντας κόμβους που έχουν την τιμή 650 (“θεματική περιοχή”) στην ιδιότητα (attribute) tag. Για κάθε τέτοιο κόμβο παίρνουμε όλα τα παιδιά του subfield και τυπώνουμε το περιεχόμενο κείμενό τους:
# iterate searching for specific attribute and print
# text of 'subfield' nodes under found elements
for e in elm:
if e.attrib['tag']=='650':
e2 = e.findall(NS+"subfield")
for itm in e2:
print itm.text
Το συνολικό πρόγραμμα έχει ως εξής:
#!/usr/bin/python
# -*- coding: utf-8 -*-
""" testing the elementtree module on LOC SRU data """
import xml.etree.ElementTree as ET
import urllib # used for web retrieval
import sys
isbn = '0596100469' # sample isbn if none given
if len(sys.argv)>1:
isbn = sys.argv[1].replace('-','')
# let's get a record from loc sru, with a specific isbn
page = urllib.urlopen("http://z3950.loc.gov:7090/voyager?version=1.1&"
"operation=searchRetrieve&query=bath.isbn="+isbn+"&maximumRecords=1")
# let's build an elementtree element now
tree = ET.parse(page)
page.close()
# mark our namespaces for clarity
NS = "{http://www.loc.gov/MARC21/slim}" # the default namespace
ZSNS = "{http://www.loc.gov/zing/srw/}"
# find all nodes in the path zs:records/zs:record/zs:recordData/record/datafield under root
# NOTE: root tag is not listed in path as it is represented by 'tree' variable.
elm = tree.findall(ZSNS+"records/"+ZSNS+"record/"+ZSNS+"recordData/"+NS+"record/"+NS+"datafield")
# iterate searching for specific attribute and print
# text of 'subfield' nodes under found elements
for e in elm:
if e.attrib['tag']=='650':
e2 = e.findall(NS+"subfield")
for itm in e2:
print itm.text