Changeset 6451


Ignore:
Timestamp:
01/02/10 16:56:43 (9 years ago)
Author:
sdonegan
Message:

Updated ExtractISO.py to rewrite URLs with ndgredirect if required. Also updated to add method for datasetAnstract; testISO.py updated for testing; dif2stubIso.py updated with method to provide xpath for extracting abstract from ISO

Location:
TI01-discovery-Ingest/trunk/v4n_MEDIN/ingestAutomation-upgrade/OAIBatch
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • TI01-discovery-Ingest/trunk/v4n_MEDIN/ingestAutomation-upgrade/OAIBatch/ExtractISO.py

    r6363 r6451  
    1414                #self.createISOdataStructure() 
    1515                 
     16                 
     17        ''' 
     18        Method to control re-writing of ISO xml with NDG redirect URL's 
     19        ''' 
     20        def generateNDGredirectURL(self, ndgRedirectURL, xmlOutputFile): 
     21                 
     22                logging.info("Generating XML copy with URLS converted to NDG redirect URL's") 
     23                 
     24                self.redirectBaseURL = ndgRedirectURL 
     25                 
     26                rewriteIsoXml = self.changeElementUrlVal(self.isoModel.urlsToChange(), xmlOutputFile) 
     27                 
     28                #import pdb 
     29                #pdb.set_trace() 
     30                #sys.exit() 
     31                 
     32                return rewriteIsoXml 
     33                 
    1634        ''' 
    1735        Simple method to allow return information on success of extraction ( __init__ method cannot return anything so use this method) 
     
    2341                logging.info("") 
    2442                 
    25                 self.root = self.getIsoXML(self.inputXMLfile)            
     43                 
     44                self.root = self.getIsoXML(self.inputXMLfile) 
     45                 
     46                self.isoFileLocation = self.inputXMLfile         
    2647                 
    2748                #self.root = self.getIsoXML('/misc/glue1/sdonegan/NDG3_workspace/buildouts/oai_document_ingester_MEDIN/ingestAutomation-upgrade/OAIBatch//data/NEODC/stub_iso/neodc.nerc.ac.uk__stubISO__dataent_11658383444211836_DIF.xml') 
     
    3354                #choose the ISO xpath definition class depending on format profile required  
    3455                self.importISOxmlDefinition(self.isoFormatToExtract) 
    35                                          
     56                                                         
    3657                #get all the required information from the chosen xpath definition class 
    3758                self.datasetID = self.getElementVal(self.isoModel.datasetID()) 
    3859                 
     60                self.datasetName = self.getElementVal(self.isoModel.dataSetName()) 
     61                 
     62                self.datasetAbstract = self.getElementVal(self.isoModel.dataSetAbstract()) 
     63                 
     64                self.datasetID = self.getElementVal(self.isoModel.datasetID()) 
     65                 
    3966                self.revisionDate = self.getElementVal(self.isoModel.metadataRevisionDate()) 
    4067                 
     
    5683                 
    5784                self.keywords = self.getElementVal(self.isoModel.keywords()) 
     85                 
     86                self.keywordsList = self.listify(self.keywords) 
    5887                 
    5988                self.boundingBoxCoordinates = self.getElementVal(self.isoModel.coordinates()) 
     
    6594                return True 
    6695         
     96         
     97        ''' 
     98        Method to generate a simple list object from a compound list set 
     99        ''' 
     100        def listify(self,listObject): 
     101                 
     102                list = [] 
     103                 
     104                for outer in listObject: 
     105                        for inner in outer:                              
     106                                list.append(inner) 
     107                                                 
     108                return list 
    67109                 
    68110        ''' 
     
    74116                allDates = [] 
    75117                returnDates = {} 
     118                 
     119                #remember, need to sort out whether there was a start and end date in the first place, or just one so can copy values over 
     120                if len(boundingDatesList) == 1: 
     121                        logging.info("Only 1 set of start and stop dates, so setting range to this..") 
     122                        returnDates['start'] = boundingDatesList[0]['start'] 
     123                        returnDates['end'] = boundingDatesList[0]['end'] 
     124                         
     125                        #convert None to 'None' 
     126                        for date in returnDates.keys(): 
     127                                if returnDates[date] is None: 
     128                                        returnDates[date] = 'None' 
     129                         
     130                        return returnDates 
    76131                 
    77132                for outer in boundingDatesList: 
     
    81136                                                #some other test here to ensure proper date object 
    82137                                                allDates.append(outer[inner]) 
    83  
     138                                                 
     139                                 
    84140                #min and max seem to work for now (to get it working) - assuming proper dateformat (restrict to YYYY-MM-DD for now) 
    85141                #TODO: use datetime library to do this properly          
     
    120176                 
    121177                 
    122                  
    123         ''' 
    124         Method to aid passing and extraction info from complex xpath tuples 
    125          
    126         Will work out whether complex or simple xpath extraction required depending on type of xpath method sent 
    127          
    128         If 'order' key present then will return a dictionary of values with the extracted value using the specified key. 
    129          
    130         ''' 
    131         def getElementVal(self,keyMethod): 
    132                  
    133                 #develop handler method to simplify 
    134                 returnValList=[]                                 
    135                 returnVal = 'None' 
    136                  
     178        ''' 
     179        Method to govern the changing of an element value (in the first instance change a url to a NDG redirect URL 
     180        ''' 
     181        def changeElementUrlVal(self,keyMethod,outputFile): 
     182                 
     183         
    137184                logging.info("******************************************************************************************") 
    138                 logging.info("Extracting xpath information for data extraction type:" + keyMethod[0]) 
     185                logging.info("Extracting xpath information for data extraction type (to change URL..):" + keyMethod[0]) 
    139186                logging.info("******************************************************************************************") 
    140187                                 
     
    142189                #first need to interpret the contents of the tuple we've been passed everything is a dictionary in the tuple apart from element 0: 
    143190                #build a map of it - do this as a dictionary with the key as the position in the tuple and the value as the element val, be it str or dictionary key 
     191                dataStruct = self.interpretTuple(keyMethod) 
     192                cnt = 0 
     193                 
     194                #this is similar to getElementVal - but no interest in ordering or returning the actual value.. 
     195                for i in dataStruct.keys()[1:]: 
     196                                                 
     197                        thisData = keyMethod[i][dataStruct[i]] 
     198                                                                 
     199                        #is dicionary a dependant value or straight xpath? 
     200                        if 'baseXpath' in thisData.keys(): 
     201                                logging.info("Extracting xml using COMPLEX dependant method for xpath def: " + str(cnt))                         
     202                                self.changeDependantURLElementVal(thisData['baseXpath'],thisData['elValXpath'],thisData['depValXpath'],thisData['depVal'])                               
     203                                                                 
     204                        if 'xpath' in thisData.keys():           
     205                                logging.info("Extracting xml using SIMPLE method for xpath def: " + str(cnt))                                            
     206                                self.changeSimpleURLElementVal(thisData['xpath'])        
     207                                                 
     208                #having returned the completed xml tree... write it to the OP file dictated.. 
     209                try: 
     210                        #rewrite this back into the xml doc                              
     211                        self.etree.write(outputFile) 
     212                        logging.info("Have successfully generated new ISO file with rewritten urls to NDG redirect format!") 
     213                         
     214                        return True 
     215                 
     216                except: 
     217                        logging.error("Could not rewrite NDG url ISO xml to; " + outputFile) 
     218                         
     219                        return False 
     220                 
     221                 
     222        ''' 
     223        Method to change an ISO element val - simple xpath value 
     224        ''' 
     225        def changeSimpleURLElementVal(self, xpath): 
     226                 
     227                #Note using single path namespath appender rather than list version.. (keeps it simpler)         
     228                xpathNS = self.appendNameSpace(xpath)            
     229                 
     230                resElementVal = [] 
     231                 
     232                try:     
     233                        rootEl = self.root.findall(xpathNS) 
     234                         
     235                except: 
     236                        logging.error("Could not find element for this xpath: " + xpath)                         
     237                         
     238                                                 
     239                #use a text 'None' rather than a None type                       
     240                for elVal in rootEl: 
     241                        if elVal is None:  
     242                                originalUrl = 'None'  
     243                        else: 
     244                                try:                     
     245                                        originalUrl = elVal.text         
     246                                        redirectURL = self.redirectBaseURL + originalUrl + '&docID=' + urllib.quote(self.datasetID[0][0]) + '&docTitle=' + urllib.quote(self.datasetName[0][0]) 
     247                                 
     248                                        #reassign... 
     249                                        elVal.text = redirectURL                                         
     250                                        logging.info("Have successfuly rewritten ndg redirect URL: " + redirectURL) 
     251                                         
     252                                except: 
     253                                        logging.error("Could not change original (simple) url!") 
     254                                         
     255                #no need to return anything -if we rewrite the doc, any successful changes will be incorporated, otherwise will be ignored 
     256         
     257        ''' 
     258        Method to change an ISO element val - compound dependant xpath values 
     259        ''' 
     260        def changeDependantURLElementVal(self,baseXpath,elXpath,depXpath,depValReqd): 
     261                 
     262                #Note using single path namespath appender rather than list version.. (keeps it simpler)         
     263                baseXpath = self.appendNameSpace(baseXpath) 
     264                                 
     265                #for path in baseXpaths: 
     266                try:                             
     267                        rootEl = self.root.findall(baseXpath) #returns an elementree object of elements in a list                                
     268                except: 
     269                        logging.error("Could not find element for this xpath: " + baseXpath) 
     270                        return 'None' 
     271                         
     272                for el in rootEl: 
     273                        thisElXpth = self.appendNameSpace(elXpath) 
     274                                                                 
     275                        thisEl = self.doFindall(el,thisElXpth) 
     276                                 
     277                        #if there's a value for the actual xpath we want, go and get the dependant value 
     278                        if thisEl != 'None': 
     279                                         
     280                                elVal = thisEl[0] 
     281                                elValTxt = elVal.text #NOTE take first one as we expect this to be the value we want 
     282                                                                         
     283                                thisEldepXpth = self.appendNameSpace(depXpath)                                   
     284                                thisDepEl = self.doFindall(el,thisEldepXpth)                                                             
     285                                         
     286                                if thisDepEl != 'None': 
     287                                                                                 
     288                                        depVal = thisDepEl[0].text 
     289                                                                         
     290                                        if depVal == depValReqd: 
     291                                                 
     292                                                try: 
     293                                                        originalUrl = elValTxt                                           
     294                                                        redirectURL = self.redirectBaseURL + originalUrl + '&docID=' + urllib.quote(self.datasetID[0][0]) + '&docTitle=' + urllib.quote(self.datasetName[0][0]) 
     295                                                                                         
     296                                                        #reassign... 
     297                                                        elVal.text = redirectURL                                                                                         
     298                                                        logging.info("Have successfuly rewritten ndg redirect URL: " + redirectURL) 
     299                                                         
     300                                                except: 
     301                                                        logging.error("Could not change original (complex) url!") 
     302                                         
     303                                                                                                                         
     304                #no need to return anything -if we rewrite the doc, any successful changes will be incorporated, otherwise will be ignored 
     305         
     306         
     307         
     308        ''' 
     309        Method to initially interpret the xpath dictionary type passed  
     310        ''' 
     311        def interpretTuple(self,keyMethod): 
     312                 
    144313                dataStruct = {} 
    145314                counter=0 
     
    156325                                 
    157326                        counter = counter + 1 
    158                  
     327                                 
     328                return dataStruct 
     329         
     330                 
     331        ''' 
     332        Method to aid passing and extraction info from complex xpath tuples 
     333         
     334        Will work out whether complex or simple xpath extraction required depending on type of xpath method sent 
     335         
     336        If 'order' key present then will return a dictionary of values with the extracted value using the specified key. 
     337         
     338        ''' 
     339        def getElementVal(self,keyMethod): 
     340                 
     341                #develop handler method to simplify 
     342                returnValList=[]                                 
     343                returnVal = 'None' 
     344                 
     345                logging.info("******************************************************************************************") 
     346                logging.info("Extracting xpath information for data extraction type:" + keyMethod[0]) 
     347                logging.info("******************************************************************************************") 
     348                                 
     349                 
     350                #first need to interpret the contents of the tuple we've been passed everything is a dictionary in the tuple apart from element 0: 
     351                #build a map of it - do this as a dictionary with the key as the position in the tuple and the value as the element val, be it str or dictionary key 
     352                dataStruct = self.interpretTuple(keyMethod) 
     353                ''' 
     354                dataStruct = {} 
     355                counter=0 
     356                for i in keyMethod: 
     357                        if type(i) is dict: 
     358                                 
     359                                #loop through the top level (remember its a dictionary of dictionaries!) 
     360                                for j in i.keys():                               
     361                                        dataStruct[counter]=j 
     362                         
     363                        #Only other data type present should be a string 
     364                        if type(i) is str: 
     365                                dataStruct[counter] = i 
     366                                 
     367                        counter = counter + 1 
     368                ''' 
    159369                 
    160370                #now iterate through the key list in dataStruct but miss First one (as its a name val!)                  
     
    293503                xpathNS = self.appendNameSpace(xpath)            
    294504                 
    295  
    296505                resElementVal = [] 
    297506                 
     
    315524                else: 
    316525                        for el in rootEl:                                        
    317                                 resElementVal.append(el.text)            
    318                 ''' 
     526                                resElementVal.append(el.text)    
     527                                 
     528                                         
     529                ''' 
     530                 
    319531                return resElementVal 
    320532                                 
     
    384596                 
    385597                #parse the xml with elementtree 
    386                 etree=ET.parse(file) 
    387                 root=etree.getroot() # should be the "gmd:MD_Metadata" element 
     598                self.etree=ET.parse(file) 
     599                root=self.etree.getroot() # should be the "gmd:MD_Metadata" element 
    388600                 
    389601                #check root element is an ISO one - use elementtree appended namespace.. 
  • TI01-discovery-Ingest/trunk/v4n_MEDIN/ingestAutomation-upgrade/OAIBatch/difConvertedto_ISO19139.py

    r6312 r6451  
    3030                 
    3131                datasetName = (self.dataSetName.__name__,{1:{'xpath':'gmd:identificationInfo/gmd:MD_DataIdentification/gmd:citation/gmd:CI_Citation/title/gco:CharacterString'}}) 
     32                 
     33                return datasetName 
     34         
     35         
     36        def dataSetAbstract(self): 
     37                ''' 
     38                See notes in metadataDates for tuple format 
     39                ''' 
     40                 
     41                datasetName = (self.dataSetAbstract.__name__,{1:{'xpath':'gmd:identificationInfo/gmd:MD_DataIdentification/gmd:abstract/gco:CharacterString'}}) 
    3242                 
    3343                return datasetName 
     
    123133                 
    124134                return keywords 
     135         
     136         
     137        def urlsToChange(self): 
     138                ''' 
     139                Method containing standard iso xpath for URL's to be changed for purposes of NDG redirect 
     140                 
     141                ''' 
     142                 
     143                urls = (self.urlsToChange.__name__,{1:{'xpath':'gmd:dataSetURI/gco:CharacterString'}}, 
     144                        {2:{                                                                     
     145                'baseXpath':'distributionInfo/gmd:MD_Distribution/transferOptions', 
     146                'elValXpath':'gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource/gmd:linkage/gmd:URL', 
     147                'depValXpath':'gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource/function/gmd:CI_onLineFunctionCode', 
     148                'depVal':'DIF:RELATED_URL'}}, 
     149                {3:{'baseXpath':'gmd:contact/gmd:CI_ResponsibleParty/gmd:contactInfo/gmd:CI_Contact/gmd:onlineResource', 
     150                                                                                                        'elValXpath':'gmd;linkage/gmd:URL', 
     151                                                                                                        'depValXpath':'function/gmd:CI_onLineFunctionCode', 
     152                                                                                                        'depVal':'DIF:DC_URL'}} 
     153                ) 
     154                 
     155                return urls 
    125156                 
    126157         
  • TI01-discovery-Ingest/trunk/v4n_MEDIN/ingestAutomation-upgrade/OAIBatch/testISO.py

    r6363 r6451  
    2828 
    2929#test dif2stubIso xml file - converted from dif via xquery 
    30 dif2stubIso_file = 'data/NEODC/stub_iso/neodc.nerc.ac.uk__stubISO__dataent_11658383444211836_DIF_multiDate.xml' 
     30#dif2stubIso_file = 'data/NEODC/stub_iso/neodc.nerc.ac.uk__stubISO__dataent_11658383444211836_DIF_multiDate.xml' 
    3131#dif2stubIso_file = 'data/NEODC/stub_iso/neodc.nerc.ac.uk__stubISO__dataent_11658383444211836_DIF_multiCoord.xml' 
    32 #dif2stubIso_file = 'data/NEODC/stub_iso/neodc.nerc.ac.uk__stubISO__dataent_11658383444211836_DIF.xml' 
     32dif2stubIso_file = 'data/NEODC/stub_iso/neodc.nerc.ac.uk__stubISO__dataent_11658383444211836_DIF.xml' 
    3333 
    3434isoData = ExtractISO(dif2stubIso_file,'dif2stubIso') 
     35 
     36 
    3537 
    3638if isoData.createISOdataStructure() is True: 
     
    4244        logging.info( "Something SERIOUSELY wrong with extractor (couldnt get at ExtractISO class)") 
    4345        sys.exit() 
     46         
     47#sys.exit() 
    4448 
    4549print "\nTesting for bounding dates (list of dictionaries) ..." 
     
    5155 
    5256accessIsoDataModel(isoData.boundingDatesRange,name) 
    53  
    54  
    5557 
    5658print "\nTesting for datasetID (List)..." 
     
    7375name = "datasetName" 
    7476accessIsoDataModel(isoData.datasetName, name) 
     77 
     78print "\nTesting for dataset abstract (List) ..." 
     79name = "datasetAbstract" 
     80accessIsoDataModel(isoData.datasetAbstract, name) 
    7581                 
    7682print "\nTesting for original format (List) ..." 
     
    9399name = "boundingBoxCoordinates" 
    94100accessIsoDataModel(isoData.boundingBoxCoordinates, name) 
     101 
     102print "\nConverting relevant URLS to NDG redirect URL!" 
     103if isoData.generateNDGredirectURL("http://scooby.dooby.doo/redirect=","./theRedirectedOutput.xml"): 
     104        print "Successfully generated redirect url xml!!" 
     105else: 
     106        print "Unsuccessfully tried to rewrite urls with ndg redirect url!" 
Note: See TracChangeset for help on using the changeset viewer.