source: TI07-MOLES/trunk/PythonCode/existInterface/eXistGeneralInterface.py @ 1457

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI07-MOLES/trunk/PythonCode/existInterface/eXistGeneralInterface.py@2278
Revision 1457, 7.5 KB checked in by domlowe, 13 years ago (diff)

removed defineNamespace method, not needed

Line 
1# Code inspired by example on eXist website.
2import urllib2, base64, urllib, urlparse, httplib, xmlrpclib, types
3
4class   InstanceObject(object):
5    def __init__(self, **kw):
6        self.dict={}
7        self.dict.update(kw)
8    def __getattr__(self,arg):
9        return self.dict[arg]
10
11class  eXist_Connector(object):
12    """Access class for eXist"""
13    def __init__(self,constants=None):
14        ''' Instantiates the eXist connector using supplied constants '''
15        if constants is None: raise 'NoExistConstants'
16        authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm()
17        authinfo.add_password(None,
18                                  constants.host,
19                                  constants.userid,
20                                  constants.password)
21        authHandler = urllib2.HTTPBasicAuthHandler(authinfo)
22        opener = urllib2.build_opener(authHandler)
23        s = constants.userid+':'+constants.password
24        z = base64.encodestring(s)[:-1] # strip trailing 12
25        opener.addheaders.append(('Authorization', 'Basic %s' % z))
26        self.http_headers = {'Authorization':'Basic %s' % z}
27        self.opener = opener
28        # also create an xmlrpc Server object
29       
30        xmlrpc_uri = '%s%s:%s@%s:%d%s' % ( 
31                                            'http://',
32                                            constants.userid,
33                                            constants.password,
34                                            constants.host,
35                                            constants.port,
36                                            constants.xmlrpc_base_path
37                                        )
38        print xmlrpc_uri
39        self.xmlrpc = xmlrpclib.Server(xmlrpc_uri)
40
41    def executeQuery(self, xquery, params={}):
42        '''Execute an xquery string, return session and summary information'''
43        xquery=xmlrpclib.Binary(xquery)
44        id = self.xmlrpc.executeQuery(xquery, params)
45        summary = self.xmlrpc.querySummary(id)
46        return id,summary
47
48    def release(self,id):
49        ''' Release an executeQuery session '''
50        self.xmlrpc.releaseQueryResult(id)
51       
52    def retrieve(self,id,pos,params={}):
53        ''' Retrieve a specific document from an executeQuery result set '''
54        return self.xmlrpc.retrieve(id,pos,params).data
55 
56    def executeChunkedQuery(self,xquery,start,number,params={}):
57        ''' Execute a query, return a specific part of the result set, and
58        dump the session automagically '''
59        xquery=xmlrpclib.Binary(xquery)
60        r=self.xmlrpc.query(xquery,number,start,params)
61        return r
62       
63class ndg_eXist(eXist_Connector):
64    ''' Adds ndg methods to a "standard" exist Connector '''
65    def __init__(self,myhost='localhost'):
66        f=file('passwords.txt','r')
67        pw={}
68        for line in f.readlines():
69            host,userid,password=line.strip().split(' ')
70            pw[host]=(userid,password)
71        eXistConstants = InstanceObject(host=myhost,
72                                userid=pw[myhost][0],
73                                password=pw[myhost][1],
74                                base_path="/exist/servlet",
75                                xmlrpc_base_path="/exist/xmlrpc",
76                                port=8080)
77       
78        eXist_Connector.__init__(self,eXistConstants)
79        self.ids={}
80       
81    def __buildquery(self,query,target):
82        '''Create an NDG full text query '''
83        s="//%s[. &='%s']"%(target,query)
84        return s#xmlrpclib.Binary(s)
85
86    def __buildParamSearch(self,param,value,target):
87        s="for $x in document()//%s where $x[.%s &= '%s'] return $x"%(target,param,value)
88        return s
89
90    def full_text(self,query,target='DIF'):
91        ''' Carry out a full text search within the "target" collection '''
92        id,summary=self.executeQuery(self.__buildquery(query,target))
93        self.ids[id]=0
94        return id,summary
95
96    def retrieveNext(self,id):
97        ''' Takes a sessionID from an existing query and gets the next document '''
98        try:
99            r=self.retrieve(id, self.ids[id])
100            self.ids[id]+=1
101            return r
102        except xmlrpclib.Fault:
103            return None
104        except KeyError:
105            return None
106   
107    def sessionRelease(self,id):
108        ''' Releases a session and removes the position counter '''
109        try:
110            self.release(id)
111            del self.ids[id]
112            return 1
113        except:
114            return 0
115   
116    def chunkedFullText(self,query,target='DIF',start=1,number=10):
117        ''' Execute a chunked full text query and return the result
118        set '''
119        return self.executeChunkedQuery(self.__buildquery(query,target),start,number,params={})
120   
121   
122    def getDIF(self,entryID):
123        ''' Get a specific DIF document from a repository by using the entryID '''
124        xq='''for $DE in collection('/db/dif')/DIF[Entry_ID='%s'] return $DE'''%entryID
125        xquery='''for $DE in collection('/db/dif')/DIF[Entry_ID='%s'] return $DE'''%entryID
126        id,summary=self.executeQuery(xq)#xquery)
127        if summary['hits']==1:
128            r=self.retrieve(id,0,{})
129            self.sessionRelease(id)
130        else:
131            r='none'
132        return r
133       
134    #getXMLRecord gets any XML record including ns:id as attribute, (added by Dom)
135    def getXMLRecord(self,collID,IDdefinition,itemID,att=None,namespaceLong=None,namespaceShort=None):
136        ''' Get a specific document from a collection in a repository by using the collection name and ID and ID element name '''
137        if att: # ID is stored in an attribute
138            if namespaceLong and namespaceShort: #if attribute has namespace e.g. gml:id
139                xq='''declare namespace %s="%s"; for $DE in collection('%s')/*[@%s='%s'] return $DE'''%(namespaceShort,namespaceLong,collID,IDdefinition,itemID)
140            else: xq='''for $DE in collection('%s')/*[@%s='%s'] return $DE'''%(collID,IDdefinition,itemID)
141        else:
142            xq='''for $DE in collection('%s')/*[%s='%s'] return $DE'''%(collID,IDdefinition,itemID)
143        id,summary=self.executeQuery(xq)
144        if summary['hits']==1:
145            r=self.retrieve(id,0,{})
146            self.sessionRelease(id)
147        else:
148            r='none'
149        return r
150   
151if __name__=="__main__":
152   
153    existDB=ndg_eXist()
154    #gepidaeDB=ndg_eXist(myhost='gepidae.esc.rl.ac.uk')
155   
156    #these both work fine
157    id,summary=existDB.full_text('coapec')
158    print 'GLUE:',summary
159    #id,summary=gepidaeDB.full_text('coapec')
160    #print 'GEPIDAE: ',summary
161   
162    #we can retrieve them all and look at them ...
163    r=1
164    while r is not None:
165        r=existDB.retrieveNext(id)
166        #if r is not None: print r
167    existDB.release(id)
168    #gepidaeDB.release(id)
169    print 'done simple'
170   
171    #now try and get the DIF documents alone:
172    #works fine: print gepidaeDB.getDIF('badc.nerc.ac.uk:DIF:dataent10')
173    print existDB.getDIF('badc.nerc.ac.uk:DIF:dataent12')
174    print 'done getDif'
175   
176    #two tests of getXMLRecord - one for a DIF, one for MOLES (added by Dom)
177    print existDB.getXMLRecord('/db/dif','Entry_ID','badc.nerc.ac.uk:DIF:dataent12')
178    print 'done getXMLRecord (DIF)'
179   
180    print existDB.getXMLRecord('/db/ndg_B_metadata','dgMetadataRecord/dgMetadataID/localIdentifier','dataent50')
181    print 'done getXMLRecord (MOLES)'
182    #print existDB.chunkedFullText('badc')
183       
184    print existDB.getXMLRecord('/db/ndg_A_metadata','gml:id','coapec_sample',att=1,namespaceLong='http://www.opengis.net/gml',namespaceShort='gml')
185    print 'done getXMLRecord with gml:id attribute (CSML)'
186   
Note: See TracBrowser for help on using the repository browser.