source: TI01-discovery-Ingest/trunk/v4n_MEDIN/ingestAutomation-upgrade/OAIBatch/ExtractISO.py @ 6614

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI01-discovery-Ingest/trunk/v4n_MEDIN/ingestAutomation-upgrade/OAIBatch/ExtractISO.py@6614
Revision 6614, 24.7 KB checked in by sdonegan, 12 years ago (diff)

Added latest updates to extract all requested info from MEDIN iso

Line 
1
2from xml.etree import ElementTree as ET
3import logging,urllib,os,sys,inspect
4
5class ExtractISO:
6
7        def __init__(self,filenameIP,isoFormat):                               
8                               
9                self.inputXMLfile = filenameIP
10                self.isoFormatToExtract = isoFormat
11               
12                #show actual values extracted from the XML in logging.info
13                self.showXMLvalues = True
14               
15                logging.info("Have initialised ISO XML Extractor")
16               
17                #self.createISOdataStructure()
18               
19               
20        '''
21        Method to control re-writing of ISO xml with NDG redirect URL's
22        '''
23        def generateNDGredirectURL(self, ndgRedirectURL, xmlOutputFile):
24               
25                logging.info("Generating XML copy with URLS converted to NDG redirect URL's")
26               
27                self.redirectBaseURL = ndgRedirectURL
28               
29                rewriteIsoXml = self.changeElementUrlVal(self.isoModel.urlsToChange(), xmlOutputFile)
30               
31               
32                #sys.exit()
33               
34                return rewriteIsoXml
35       
36       
37       
38        '''
39        Method to map ISO values to Discovery Database columns
40       
41        returns a dictionary where key is
42    '''
43        def mapIsoFieldsToDBcolumns(self):
44               
45                return {'originalFormat':'original_format_name', \
46        'originalFormatVersion':'original_format_version',\
47        'datasetAbstract':'dataset_abstract', \
48        'resourceType':'resource_type_ts_vector', \
49        'topicCategory':'topic_category_ts_vector', \
50        'lineage':'lineage_ts_vector', \
51        'publicAccessLimitations':'limitations_public_access_ts_vector', \
52        'dataOriginator':'data_originator',\
53        'metadataUpdateDate':'dataset_metadata_update_date', \
54        'dataFormat':'original_format_name'}
55       
56       
57               
58        '''
59        Simple method to allow return information on success of extraction ( __init__ method cannot return anything so use this method)
60        '''
61        def createISOdataStructure(self):
62               
63                logging.info("")
64                logging.info("********************************************************************************************************************************************")
65                logging.info("****************** Creating ISO data structure from " + self.inputXMLfile + "****************** ")
66                logging.info("********************************************************************************************************************************************")
67                logging.info("")
68               
69               
70                self.root = self.getIsoXML(self.inputXMLfile)
71               
72                self.isoFileLocation = self.inputXMLfile       
73               
74                #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')
75               
76                if self.root is None:
77                        logging.error("Detected possible problem with input xml - cannot parse it!")
78                        return False
79               
80                #choose the ISO xpath definition class depending on format profile required
81                self.importISOxmlDefinition(self.isoFormatToExtract)
82                                                       
83                #get all the required information from the chosen xpath definition class
84                self.datasetID = self.getElementVal(self.isoModel.datasetID())
85               
86                self.datasetName = self.getElementVal(self.isoModel.dataSetName())
87               
88                self.datasetAbstract = self.getElementVal(self.isoModel.dataSetAbstract())
89               
90                self.datasetID = self.getElementVal(self.isoModel.datasetID())
91               
92                self.revisionDate = self.getElementVal(self.isoModel.metadataRevisionDate())
93               
94                self.createDate = self.getElementVal(self.isoModel.metadataCreationDate())
95                               
96                self.datasetName = self.getElementVal(self.isoModel.dataSetName())             
97               
98                self.boundingDates = self.getElementVal(self.isoModel.boundingDates())
99               
100                self.boundingDatesRange = self.boundingDateRange(self.boundingDates)   
101               
102                self.originalFormat = self.getElementVal(self.isoModel.originalFormat())
103               
104                self.authors = self.getElementVal(self.isoModel.authors())
105                               
106                self.datacentreName = self.getElementVal(self.isoModel.dataCentreName())
107               
108                self.parameters = self.getElementVal(self.isoModel.parameters()) 
109               
110                self.keywords = self.getElementVal(self.isoModel.keywords())
111               
112                self.keywordsList = self.listify(self.keywords)
113               
114                self.boundingBoxCoordinates = self.getElementVal(self.isoModel.coordinates())                           
115               
116                #These are the MEDIN requested extra fields - make optional
117                try:
118                        self.originalFormatVersion = self.getElementVal(self.isoModel.originalFormatVersion())
119                except:
120                        self.originalFormatVersion = None
121               
122                try:
123                        self.publicationDate = self.getElementVal(self.isoModel.metadataPublicationDate())
124                except:
125                        self.publicationDate = None
126                       
127                try:
128                        self.resourceType = self.getElementVal(self.isoModel.resourceType())
129                except:
130                        self.resourceType = None
131               
132                try:
133                        self.topicCategory = self.getElementVal(self.isoModel.topicCategory())
134                except:
135                        self.topicCategory = None
136               
137                try:
138                        self.lineage = self.getElementVal(self.isoModel.lineage())
139                except:
140                        self.lineage = None
141               
142                try:
143                        self.publicAccessLimitations = self.getElementVal(self.isoModel.publicAccessLimitations())
144                except:
145                        self.publicAccessLimitations = None
146                       
147                try:
148                        self.dataOriginator= self.getElementVal(self.isoModel.dataOriginator())
149                except:
150                        self.dataOriginator = None
151               
152                try:
153                        self.dataFormat = self.getElementVal(self.isoModel.originalFormat())
154                except:
155                        self.dataFormat = None
156               
157                try:
158                        self.metadataUpdateDate = self.getElementVal(self.isoModel.metadataUpdateDate())
159                except:
160                        self.metadataUpdateDate = None
161                       
162                       
163                try:
164                        self.originalFormatName = self.getElementVal(self.isoModel.originalFormat())
165                except:
166                        self.originalFormatName = None
167                       
168                try:
169                        self.originalFormatVersion = self.getElementVal(self.isoModel.originalFormatVersion())
170                except:
171                        self.originalFormatVersion = None
172                       
173                import pdb
174                pdb.set_trace()
175               
176                logging.info("")
177                logging.info(" ****************** Completed rendering ISO xml into data structure! ****************** ")
178                logging.info("")
179               
180                return True
181       
182       
183        '''
184        Method to generate a simple list object from a compound list set
185        '''
186        def listify(self,listObject):
187               
188                list = []
189               
190                for outer in listObject:
191                        for inner in outer:                             
192                                list.append(inner)
193                                               
194                return list
195               
196        '''
197        Method to return start and end dates from a sequence of dates such as that found returned using the xpath defn from boundingDates
198        '''
199        def boundingDateRange(self,boundingDatesList):
200               
201                #generate a simple list of all dates
202                allDates = []
203                returnDates = {}
204               
205                #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
206                if len(boundingDatesList) == 1:
207                        logging.info("Only 1 set of start and stop dates, so setting range to this..")
208                        returnDates['start'] = boundingDatesList[0]['start']
209                        returnDates['end'] = boundingDatesList[0]['end']
210                       
211                        #convert None to 'None'
212                        for date in returnDates.keys():
213                                if returnDates[date] is None:
214                                        returnDates[date] = 'None'
215                       
216                        return returnDates
217               
218                for outer in boundingDatesList:
219                        for inner in outer.keys():
220                                if outer[inner] is not None:
221                                        if outer[inner] != 'None':
222                                                #some other test here to ensure proper date object
223                                                allDates.append(outer[inner])
224                                               
225                               
226                #min and max seem to work for now (to get it working) - assuming proper dateformat (restrict to YYYY-MM-DD for now)
227                #TODO: use datetime library to do this properly         
228                returnDates['start'] = min(allDates)
229                returnDates['end'] = max(allDates)
230               
231                return returnDates
232       
233       
234               
235        '''
236        Method to import specific ISO xpath definition class depending on the profile used
237        '''
238        def importISOxmlDefinition(self,format):
239               
240                '''
241                MEDIN Profile v2.3 (date? - MEDIN upgrade dev)
242                '''
243               
244                logging.info("Format chosen: " + format)
245               
246               
247               
248                #Dynamically import module of correct profile...
249                import_string = "from " + format + " import " + format + " as iso"
250               
251                try:
252                        exec import_string
253                except:
254                        logging.error("Could not import xpath class for: " + format)
255                        sys.exit()
256               
257                self.isoModel = iso()
258               
259               
260        '''
261        Method to govern the changing of an element value (in the first instance change a url to a NDG redirect URL
262        '''
263        def changeElementUrlVal(self,keyMethod,outputFile):
264               
265       
266                logging.info("******************************************************************************************")
267                logging.info("Extracting xpath information for data extraction type (to change URL..):" + keyMethod[0])
268                logging.info("******************************************************************************************")
269                               
270               
271                #first need to interpret the contents of the tuple we've been passed everything is a dictionary in the tuple apart from element 0:
272                #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
273                dataStruct = self.interpretTuple(keyMethod)
274                cnt = 0
275               
276                #this is similar to getElementVal - but no interest in ordering or returning the actual value..
277                for i in dataStruct.keys()[1:]:
278                                               
279                        thisData = keyMethod[i][dataStruct[i]]
280                                                               
281                        #is dicionary a dependant value or straight xpath?
282                        if 'baseXpath' in thisData.keys():
283                                logging.info("Extracting xml using COMPLEX dependant method for xpath def: " + str(cnt))                       
284                                self.changeDependantURLElementVal(thisData['baseXpath'],thisData['elValXpath'],thisData['depValXpath'],thisData['depVal'])                             
285                                                               
286                        if 'xpath' in thisData.keys():         
287                                logging.info("Extracting xml using SIMPLE method for xpath def: " + str(cnt))                                           
288                                self.changeSimpleURLElementVal(thisData['xpath'])       
289                                                                               
290                #having returned the completed xml tree... write it to the OP file dictated..
291                try:
292                        #rewrite this back into the xml doc                             
293                        self.etree.write(outputFile)
294                        logging.info("Have successfully generated new ISO file with rewritten urls to NDG redirect format!")
295                       
296                        return True
297               
298                except:
299                        logging.error("Could not rewrite NDG url ISO xml to; " + outputFile)
300                       
301                        return False
302               
303               
304        '''
305        Method to change an ISO element val - simple xpath value
306        '''
307        def changeSimpleURLElementVal(self, xpath):
308               
309                #Note using single path namespath appender rather than list version.. (keeps it simpler)       
310                xpathNS = self.appendNameSpace(xpath)           
311               
312                resElementVal = []
313               
314                try:   
315                        rootEl = self.root.findall(xpathNS)
316                       
317                except:
318                        logging.error("Could not find element for this xpath: " + xpath)                       
319                       
320                                               
321                #use a text 'None' rather than a None type                     
322                for elVal in rootEl:
323                        if elVal is None: 
324                                originalUrl = 'None' 
325                        else:
326                                try:                   
327                                        originalUrl = elVal.text       
328                                        redirectURL = self.redirectBaseURL + originalUrl + '&docID=' + urllib.quote(self.datasetID[0][0]) + '&docTitle=' + urllib.quote(self.datasetName[0][0])
329                               
330                                        #reassign...
331                                        elVal.text = redirectURL                                       
332                                        logging.info("Have successfuly rewritten ndg redirect URL: " + redirectURL)
333                                       
334                                except:
335                                        logging.error("Could not change original (simple) url!")
336               
337                       
338                #no need to return anything -if we rewrite the doc, any successful changes will be incorporated, otherwise will be ignored
339       
340        '''
341        Method to change an ISO element val - compound dependant xpath values
342        '''
343        def changeDependantURLElementVal(self,baseXpath,elXpath,depXpath,depValReqd):
344               
345                #Note using single path namespath appender rather than list version.. (keeps it simpler)       
346                baseXpath = self.appendNameSpace(baseXpath)
347                               
348                #for path in baseXpaths:
349                try:                           
350                        rootEl = self.root.findall(baseXpath) #returns an elementree object of elements in a list                               
351                except:
352                        logging.error("Could not find element for this xpath: " + baseXpath)
353                        return 'None'
354                       
355                for el in rootEl:
356                        thisElXpth = self.appendNameSpace(elXpath)
357                                                               
358                        thisEl = self.doFindall(el,thisElXpth)
359                               
360                        #if there's a value for the actual xpath we want, go and get the dependant value
361                        if thisEl != 'None':
362                                       
363                                elVal = thisEl[0]
364                                elValTxt = elVal.text #NOTE take first one as we expect this to be the value we want
365                                                                       
366                                thisEldepXpth = self.appendNameSpace(depXpath)                                 
367                                thisDepEl = self.doFindall(el,thisEldepXpth)                                                           
368                                       
369                                if thisDepEl != 'None':
370                                                                               
371                                        depVal = thisDepEl[0].text
372                                                                       
373                                        if depVal == depValReqd:
374                                               
375                                                try:
376                                                        originalUrl = elValTxt                                         
377                                                        redirectURL = self.redirectBaseURL + originalUrl + '&docID=' + urllib.quote(self.datasetID[0][0]) + '&docTitle=' + urllib.quote(self.datasetName[0][0])
378                                                                                       
379                                                        #reassign...
380                                                        elVal.text = redirectURL                                                                                       
381                                                        logging.info("Have successfuly rewritten ndg redirect URL: " + redirectURL)
382                                                       
383                                                except:
384                                                        logging.error("Could not change original (complex) url!")
385                                       
386                                                                                                                       
387                #no need to return anything -if we rewrite the doc, any successful changes will be incorporated, otherwise will be ignored
388               
389       
390        '''
391        Method to initially interpret the xpath dictionary type passed
392        '''
393        def interpretTuple(self,keyMethod):
394               
395                dataStruct = {}
396                counter=0
397                for i in keyMethod:
398                        if type(i) is dict:
399                               
400                                #loop through the top level (remember its a dictionary of dictionaries!)
401                                for j in i.keys():                             
402                                        dataStruct[counter]=j
403                       
404                        #Only other data type present should be a string
405                        if type(i) is str:
406                                dataStruct[counter] = i
407                               
408                        counter = counter + 1
409                               
410                return dataStruct
411       
412               
413        '''
414        Method to aid passing and extraction info from complex xpath tuples
415       
416        Will work out whether complex or simple xpath extraction required depending on type of xpath method sent
417       
418        If 'order' key present then will return a dictionary of values with the extracted value using the specified key.
419       
420        '''
421        def getElementVal(self,keyMethod):
422               
423                #develop handler method to simplify
424                returnValList=[]                               
425                returnVal = 'None'
426               
427                logging.info("******************************************************************************************")
428                logging.info("Extracting xpath information for data extraction type:" + keyMethod[0])
429                logging.info("******************************************************************************************")
430                               
431                showValue = self.showXMLvalues
432               
433                #first need to interpret the contents of the tuple we've been passed everything is a dictionary in the tuple apart from element 0:
434                #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
435                dataStruct = self.interpretTuple(keyMethod)
436                '''
437                dataStruct = {}
438                counter=0
439                for i in keyMethod:
440                        if type(i) is dict:
441                               
442                                #loop through the top level (remember its a dictionary of dictionaries!)
443                                for j in i.keys():                             
444                                        dataStruct[counter]=j
445                       
446                        #Only other data type present should be a string
447                        if type(i) is str:
448                                dataStruct[counter] = i
449                               
450                        counter = counter + 1
451                '''
452               
453                #now iterate through the key list in dataStruct but miss First one (as its a name val!)                 
454                valueList = []
455                ordering = False
456               
457                cnt = 1
458               
459                for i in dataStruct.keys()[1:]:
460                                               
461                        thisData = keyMethod[i][dataStruct[i]]
462                                                               
463                        #is dicionary a dependant value or straight xpath?
464                        if 'baseXpath' in thisData.keys():
465                                logging.info("Extracting xml using COMPLEX dependant method for xpath def: " + str(cnt))                       
466                                returnVal = self.returnDependantElementVal(thisData['baseXpath'],thisData['elValXpath'],thisData['depValXpath'],thisData['depVal'],showValue)                           
467                                valueList.append(returnVal)
468                                                               
469                        if 'xpath' in thisData.keys():         
470                                logging.info("Extracting xml using SIMPLE method for xpath def: " + str(cnt))                                           
471                                returnVal =  self.returnSimpleElementVal(thisData['xpath'],showValue)                                                           
472                                valueList.append(returnVal)
473                                                               
474                        #is there any ordering info required - if so, order the return list according to the ordering tuple
475                        if 'order' in keyMethod[i].keys():
476                                logging.info("Returning a dictionary of paired values as ordering requested for xpath (number of xpath defs MUST match ordering vals available")                       
477                                ordering = True                         
478                                orderingList = thisData
479                               
480                        else:
481                                logging.info("Returning a simple list of values for xpath def: " + str (cnt))
482                               
483                        cnt = cnt + 1
484                       
485                #if ordering is required, create a corresponding dictionary of ordered values                                   
486                if ordering:
487                       
488                        #logging.INFO("Ordering data by specified order information!")
489                        logging.info("ordering information now!")
490                       
491                        '''FIRST need to group information together in correct order (i.e. elementtree groups all starts in one list, then all ends etc
492                        i.e. [[start1,start2],[end1,end2]] to [[start1,end1],[start2,end2]]
493                        '''
494                        #import pdb
495                        #pdb.set_trace()
496                        #check that number of number of elements in ordering list is not less than number of items in list to be ordered!
497                        #if multiple sets to be ordered, check numbers and return as dictionary
498                        checkCompLnth = len(valueList[0])
499                        for list in valueList:
500                                if len(list) != checkCompLnth:
501                                        logging.error("Sub component lists are of unequal length - CANNOT order!!")
502                                        return 'None'
503                               
504                        #outer loop should be the number of elements in the sublists..
505                        outer = []
506                        for localPos in range(0,checkCompLnth):
507                                inner=[]
508                                #inner loop should be the number of lists corresponding to repeating subelements                       
509                                for listPos in range(0,len(valueList)):
510                                       
511                                                inner.append(valueList[listPos][localPos])
512                                #append to outer loop
513                                outer.append(inner)                                                     
514                       
515                        for returnedList in outer:
516                               
517                                #create a disctionary for this round (will append it later to the return version)
518                                orderedValsSub = {}
519                                                                               
520                                if len(returnedList) != len(orderingList):
521                                        logging.error("Ordering List length does not match length of list to be ordered! (NOTE: can only order where lengths match!)")
522                                        returnValList.append('None')
523                               
524                                else:           
525                                        #go through valueList and extract values in correct position and build dictionary
526                                        for i in orderingList.keys():
527                                               
528                                                orderedValsSub[i] = returnedList[orderingList[i]-1] # remember there's an offset as '0' not used in these vals
529                               
530                               
531                                        returnValList.append(orderedValsSub)
532                       
533                        return returnValList
534                       
535                else:
536                        return valueList
537                       
538                       
539        '''
540        Method to return a list of values of an element value dependant on another element value held within the local tree
541        i.e. return a specific string val depending on a local code val in ISO
542       
543        if element exists and any dependant value present matches the expected value, the element value is returned as part of a list,
544        otherwise an empty list is returned
545        '''
546        def returnDependantElementVal(self,baseXpath,elXpath,depXpath,depValReqd,showValue=False):
547                       
548                #Note using single path namespath appender rather than list version.. (keeps it simpler)       
549                baseXpath = self.appendNameSpace(baseXpath)
550               
551                resDependantVal = []
552               
553                #for path in baseXpaths:
554                try:                           
555                        rootEl = self.root.findall(baseXpath) #returns an elementree object of elements in a list                               
556                except:
557                        logging.error("Could not find element for this xpath: " + baseXpath)
558                        return 'None'
559                       
560                for el in rootEl:
561                        thisElXpth = self.appendNameSpace(elXpath)
562                                                               
563                        thisEl = self.doFindall(el,thisElXpth)
564                               
565                        #if there's a value for the actual xpath we want, go and get the dependant value
566                        if thisEl != 'None':
567                                       
568                                elVal = thisEl[0].text #NOTE take first one as we expect this to be the value we want
569                                                                       
570                                thisEldepXpth = self.appendNameSpace(depXpath)                                 
571                                thisDepEl = self.doFindall(el,thisEldepXpth)                                                           
572                                       
573                                if thisDepEl != 'None':
574                                                                               
575                                        depVal = thisDepEl[0].text
576                                                                       
577                                        if depVal == depValReqd:
578                                               
579                                                if showValue is True:
580                                                        logging.info("")
581                                                        logging.info("          Element Value: " + elVal)
582                                                        logging.info("")
583                                               
584                                                resDependantVal.append(elVal)
585                                                                                                                                                       
586                return resDependantVal
587       
588        '''
589        Method to extract a value from the doc using a simple xpath.  If no element found or no data present then None is returned
590        '''
591        def returnSimpleElementVal(self,xpath,showValue=False):
592               
593                #Note using single path namespath appender rather than list version.. (keeps it simpler)       
594                xpathNS = self.appendNameSpace(xpath)           
595               
596                resElementVal = []
597               
598                try:   
599                        rootEl = self.root.findall(xpathNS)
600                       
601                except:
602                        logging.error("Could not find element for this xpath: " + xpath)                       
603                        return ['None']
604                                               
605                #use a text 'None' rather than a None type
606               
607                for elVal in rootEl:
608                        if elVal is None:
609                                resElementVal.append('None')
610                        else:
611                                value = elVal.text
612                                if (showValue is True) and (value is not None):
613                                        logging.info("")
614                                        logging.info("          Element Value: " + value)
615                                        logging.info("")
616                                       
617                                resElementVal.append(value)
618                '''     
619                if rootEl[0].text is None:                                     
620                        resElementVal.append('None')
621                else:
622                        for el in rootEl:                                       
623                                resElementVal.append(el.text)   
624                               
625                                       
626                '''
627               
628                return resElementVal
629                               
630       
631        '''
632        Method to run an elementtree findall on ns appended path in the supplied element and return list
633        returns None if nothing found
634        '''
635        def doFindall(self,el,thisElXpth):
636                               
637                try:
638                        thisElXpthEl = el.findall(thisElXpth)
639                       
640                        if len(thisElXpthEl) == 0:
641                                thisElXpthEl = 'None'
642                except:
643                        thisElXpthEl = 'None'
644               
645               
646                return thisElXpthEl
647               
648               
649        '''
650        Method to extract actual value from xml doc - expects a list of namespace qualified xpaths and will return corresponding list of values
651        '''
652        def getXmlVal(self,paths):
653               
654                xmlVals = []
655                               
656                for path in paths:
657                        try:
658                                xmlVals.append(self.root.find(path).text)                       
659                        except:
660                                logging.error("Could not extract value for xpath: " + path)
661                                xmlVals.append('null')
662                               
663                return xmlVals                                 
664               
665        '''
666        Method to hold a dictionary linking namespace prefixes to URLs
667        '''
668        def isoNameSpaces(self):
669               
670                isoNs = {'gmd':'http://www.isotc211.org/2005/gmd','gco':'http://www.isotc211.org/2005/gco',
671                                'gmx':'http://www.isotc211.org/2005/gmx','gml':'http://www.opengis.net/gml/3.2',
672                                'none':'','gts':'http://www.isotc211.org/2005/gts','gsr':'http://www.isotc211.org/2005/gsr',
673                                'gss':'http://www.isotc211.org/2005/gss'
674                                }
675               
676                return isoNs
677       
678       
679        '''
680        Method to return DEFAULT namespace in elementtree format of ISO profile used (i.e. should be gmd)
681        (to deal with those elements with no prefix)
682        '''
683        def defaultIsoNamespace(self):
684                return 'gmd'
685               
686       
687       
688        '''
689        Method to extract root element of XML file specified using elementtree
690        '''     
691        def getIsoXML(self,file):
692               
693                logging.info("Getting xml root element")
694               
695                #parse the xml with elementtree
696                self.etree=ET.parse(file)
697                root=self.etree.getroot() # should be the "gmd:MD_Metadata" element
698               
699                #avoid ns0 and ns1 etc etc namespaces when rewriting this ET
700                logging.info("Sorting out namespaces so can properly rewrite ISO xml..")
701                for ns in self.isoNameSpaces().keys():         
702                        if ns != 'None':                                               
703                                ET._namespace_map[self.isoNameSpaces()[ns]] = ns
704               
705                               
706                #check root element is an ISO one - use elementtree appended namespace..
707                if root.tag != '{http://www.isotc211.org/2005/gmd}MD_Metadata':
708                        logging.error("XML document does not appear to be ISO (not gmd:MD_Metadata)!!")                 
709                        return None
710       
711                return root
712               
713               
714        '''
715        Method to convert the given xpath list to a namespace abbreviated version so elementtree can handle it (grrr.). 
716        Will return a list of corresponding namespace qualified xpaths - if errors a 'null' will be placed.
717        '''
718        def appendNameSpaceList(self,paths):
719               
720                nameSpaceAppendedPaths = []
721               
722               
723                for path in paths:             
724                       
725                        pathElements = path.split('/')
726                       
727                        #note due to crappy elementtree have to avoid initial "/"
728                        count = 0
729                        for element in pathElements:
730                               
731                                try:                                   
732                                        if ':' in element:                                             
733                                                splitElement = element.split(':')
734                                                nsPrefix,nsElement = splitElement[0],splitElement[1]
735                                        else:
736                                                #use default namespace                                         
737                                                nsPrefix = self.defaultIsoNamespace()
738                                                nsElement = element
739                                       
740                                        if count == 0:
741                                               
742                                                #appendedPath = self.returnNS() + element
743                                                appendedPath = '{' + self.isoNameSpaces()[nsPrefix] +'}' + nsElement
744                                        else:
745                                               
746                                                appendedPath = appendedPath + '/{' + self.isoNameSpaces()[nsPrefix] +'}' + nsElement
747                                       
748                                        count += 1
749                                except:
750                                        appendedPath = 'null'
751                                        logging.error("Could not change to elementtree ns xpath")
752                                                       
753                        #clear up any blank namespace prefixes
754                        appendedPath = appendedPath.replace('{}','')
755                       
756                        nameSpaceAppendedPaths.append(appendedPath)
757
758                return nameSpaceAppendedPaths
759       
760        '''
761        Method to convert the given xpath to a namespace abbreviated version so elementtree can handle it (grrr.). 
762        Will return an equivalent namespace qualified xpath - if errors a 'null' will be placed.
763        '''
764        def appendNameSpace(self,path):
765               
766                nameSpaceAppendedPath = ''
767               
768                pathElements = path.split('/')
769                       
770                #note due to crappy elementtree have to avoid initial "/"
771                count = 0
772                for element in pathElements:
773                               
774                        try:                                   
775                                if ':' in element:                                             
776                                        splitElement = element.split(':')
777                                        nsPrefix,nsElement = splitElement[0],splitElement[1]
778                                else:
779                                        #use default namespace                                         
780                                        nsPrefix = self.defaultIsoNamespace()
781                                        nsElement = element
782                                       
783                                if count == 0:
784                                               
785                                        #appendedPath = self.returnNS() + element
786                                        appendedPath = '{' + self.isoNameSpaces()[nsPrefix] +'}' + nsElement
787                                else:                                           
788                                        appendedPath = appendedPath + '/{' + self.isoNameSpaces()[nsPrefix] +'}' + nsElement
789                                       
790                                count += 1
791                        except:
792                                appendedPath = 'null'
793                                logging.error("Could not change to elementtree ns xpath")
794                                                       
795                #clear up any blank namespace prefixes
796                nameSpaceAppendedPath = appendedPath.replace('{}','')
797               
798                return nameSpaceAppendedPath
Note: See TracBrowser for help on using the repository browser.