source: ndgCommon/trunk/ndg/common/xmldb/xquery/dif2stubISO.xq @ 7713

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/ndgCommon/trunk/ndg/common/xmldb/xquery/dif2stubISO.xq@7713
Revision 7713, 23.8 KB checked in by sdonegan, 10 years ago (diff)

Significant update to allow much better conversion of dif9.4 to NERC DMS 0.7 - concentrates on difs from BODC, BGS and BAS.

Line 
1(:Development DIF2ISO xquery - designed to convert most important DIF elements and produce a "stub" iso:
2
3Steve Donegan CEDA RALSpace 2010
4
5    - 09/11/2010: Significantly updated conversion -  now produces records more conformant with NERC DMS 0.7
6
7:)
8
9(: NOTE: stored these directly into eXist - taken from current head ndgCommon - 26/11/09 :)
10(:import module namespace voclib='http://ndg.nerc.ac.uk/xquery/lib/vocab' at 'xmldb:exist:///db/xquery/lib/Vocabs/vocab_xquery_lib.xquery';
11import module namespace inputParse='http://ndg.nerc.ac.uk/xquery/lib/inputParse' at 'xmldb:exist:///db/xquery/lib/Utilities/inputParse_xquery_lib.xquery'; :)
12
13(:Production -use these :)
14import module namespace voclib='http://ndg.nerc.ac.uk/xquery/lib/vocab' at 'vocab_xquery_lib.xquery';
15import module namespace inputParse='http://ndg.nerc.ac.uk/xquery/lib/inputParse' at 'inputParse_xquery_lib.xquery';
16import module namespace isolib='http://ndg.nerc.ac.uk/xquery/lib/iso_utilities' at 'isoUtilities_xquery_lib.xquery';
17
18(: default NS of the ISO metadata :)
19declare default element namespace 'http://www.isotc211.org/2005/gmd';
20
21(: NS of the xml we're reading from :)
22declare namespace dif='http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/';
23declare namespace ns0='http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/';
24
25(: other NS we need to produce the stub ISO :)
26declare namespace gmd='http://www.isotc211.org/2005/gmd';
27declare namespace xsi='http://www.w3.org/2001/XMLSchema-instance';
28declare namespace gco='http://www.isotc211.org/2005/gco';
29declare namespace gmx='http://www.isotc211.org/2005/gmx';
30declare namespace gml='http://www.opengis.net/gml/3.2';
31declare namespace xlink='http://www.w3.org/1999/xlink';
32
33(: development stuff for testing against ceda bora eXist :)
34(:
35declare variable $targetCollection as xs:string := '/db/DIF/neodc.nerc.ac.uk/';
36declare variable $thisDateTime as xs:string := '2009-12-01T17:00:00';
37declare variable $input_repository as xs:string := 'neodc.nerc.ac.uk';
38declare variable $input_repository_local as xs:string := 'neodc.nerc.ac.uk';
39declare variable $input_entry_id as xs:string := 'neodc.nerc.ac.uk:DIF:dataent_11658383444211836';
40declare variable $output_local_id as xs:string := 'dataent_11658383444211836';
41:)
42
43(: BODC Test DIF
44declare variable $targetCollection as xs:string := 'BODC_1048086_DIF.xml';
45declare variable $input_repository as xs:string := 'grid.bodc.nerc.ac.uk';
46declare variable $input_repository_local as xs:string := 'grid.bodc.nerc.ac.uk';
47declare variable $input_entry_id as xs:string := 'grid.bodc.nerc.ac.uk:DIF:EDMED1048086';
48declare variable $output_local_id as xs:string := 'oai%3Agrid.bodc.nerc.ac.uk%3A1048086_DIF'; :)
49
50(: BAS Test DIF
51declare variable $targetCollection as xs:string := 'BAS_00002.xml';
52declare variable $input_repository as xs:string := 'bas.nerc.ac.uk';
53declare variable $input_repository_local as xs:string := 'bas.nerc.ac.uk';
54declare variable $input_entry_id as xs:string := 'GB-NERC-BAS-AEDC-00002';
55declare variable $output_local_id as xs:string := 'GB-NERC-BAS-AEDC-00002_DIF'; :)
56 
57
58(: BGS Test DIF
59declare variable $targetCollection as xs:string := 'BGS_13480070.xml';
60declare variable $input_repository as xs:string := 'bgs.nerc.ac.uk';
61declare variable $input_repository_local as xs:string := 'bgs.nerc.ac.uk';
62declare variable $input_entry_id as xs:string := '13480070';
63declare variable $output_local_id as xs:string := '13480070_DIF';
64:)
65
66
67(: Production vals :)
68declare variable $targetCollection as xs:string := 'TargetCollection';
69declare variable $input_repository as xs:string := 'RepositoryID';
70declare variable $input_repository_local as xs:string := 'repository_localid';
71declare variable $input_entry_id as xs:string := 'Input_Entry_ID';
72declare variable $output_local_id as xs:string := 'LocalID';
73
74declare variable $thisDateTime as xs:string := substring(current-dateTime() cast as xs:string,1,19);
75
76(: Loop through the dif and pick the important stuff we need to produce a stub iso :)
77for $DIF in doc($targetCollection)/dif:DIF[dif:Entry_ID=$input_entry_id]
78
79    (:define string variable for publication and creation dates comprised of comma delimited list from ATOM elements:)
80let $publicationCreationDates := concat(data($DIF/dif:Last_DIF_Revision_Date),"=",string('revision'),",",data($DIF/dif:DIF_Creation_Date),"=",string("creation"),",",data($DIF/dif:Data_Set_Citation/dif:Dataset_Release_Date),"=",string("publication"))
81
82
83return
84element gmd:MD_Metadata {
85
86    (: add various namespaces
87    attribute xmlns:gco {"http://www.isotc211.org/2005/gco"}, :)   
88   
89    (:
90    attribute xmlns:gmx {"http://www.isotc211.org/2005/gmx"},
91    attribute xmlns:gml{"http://www.opengis.net/gml/3.2"},
92    attribute xmlns:xlink {"http://www.w3.org/1999/xlink"}, 
93    attribute xmlns:geonet {"http://www.fao.org/geonetwork"},
94    :)
95    (: Unique Identifier :)
96    element gmd:fileIdentifier {
97   
98        element gco:CharacterString {   
99          data($DIF/dif:Entry_ID)
100        }
101       
102      }, (: /gmd:fileIdentifier :)
103     
104       (: initial contact element should be main METADATA  pointOfContact :)
105   
106       (:BODC & BGS records - find "technical contact" - this is their "pointOfContact" :)
107       if ($DIF/dif:Personnel/dif:Role[.='Technical Contact']) then
108           
109           (:fudge to get DC name - if email in personnel matches that of email in data_center_personnel then take the data_center name :)
110           if ($DIF/dif:Personnel/dif:Contact_Address/dif:Postal_Code = $DIF/dif:Data_Center/dif:Personnel/dif:Contact_Address/dif:Postal_Code) then               
111               (:If no name supplied, give them the DC role name - this should get the BODC & BGS... :)
112               
113               if ($DIF/dif:Personnel/dif:First_Name = '') then
114                   isolib:pointOfContact (data($DIF/dif:Data_Center/dif:Data_Center_Name/dif:Short_Name),
115                   $DIF/dif:Personnel[1]/dif:Role,string(''),
116                   string('pointOfContact'),
117                   $DIF/dif:Personnel[1]/dif:Phone,
118                   $DIF/dif:Personnel[1]/dif:Contact_Address,
119                   $DIF/dif:Personnel[1]/dif:Contact_Address/dif:City,
120                   $DIF/dif:Personnel[1]/dif:Contact_Address/dif:Postal_Code,
121                   $DIF/dif:Personnel[1]/dif:Email)
122               else
123               (: otherwise use the supplied :)
124                   isolib:pointOfContact (data($DIF/dif:Data_Center/dif:Data_Center_Name/dif:Short_Name),
125                   concat($DIF/dif:Personnel[1]/dif:First_Name," ",$DIF/dif:Personnel[1]/dif:Last_Name),string(''),
126                   string('pointOfContact'),
127                   $DIF/dif:Personnel[1]/dif:Phone,
128                   $DIF/dif:Personnel[1]/dif:Contact_Address,
129                   $DIF/dif:Personnel[1]/dif:Contact_Address/dif:City,
130                   $DIF/dif:Personnel[1]/dif:Contact_Address/dif:Postal_Code,
131                   $DIF/dif:Personnel[1]/dif:Email)
132                             
133            else
134            (: if center name doesnt match, just use catch all string :)
135                isolib:pointOfContact (string('Participating NERC Data Centre'),
136                   concat($DIF/dif:Personnel[1]/dif:First_Name," ",$DIF/dif:Personnel[1]/dif:Last_Name), string(''),
137                   string('pointOfContact'),
138                   $DIF/dif:Personnel[1]/dif:Phone,
139                   $DIF/dif:Personnel[1]/dif:Contact_Address,
140                   $DIF/dif:Personnel[1]/dif:Contact_Address/dif:City,
141                   $DIF/dif:Personnel[1]/dif:Contact_Address/dif:Postal_Code,
142                   $DIF/dif:Personnel[1]/dif:Email)
143                   
144        else(),
145     
146      (:BAS Specialism now - find personnel/role = Data Center Contact.. :)
147      if ($DIF/dif:Data_Center/dif:Personnel/dif:Role[.='Data Center Contact']) then
148            isolib:pointOfContact ($DIF/dif:Data_Center/dif:Data_Center_Name/dif:Short_Name,
149                   concat($DIF/dif:Data_Center/dif:Personnel[1]/dif:First_Name," ",$DIF/dif:Data_Center/dif:Personnel[1]/dif:Last_Name), string(''),
150                   string('pointOfContact'),
151                   $DIF/dif:Data_Center/dif:Personnel[1]/dif:Phone,
152                   $DIF/dif:Data_Center/dif:Personnel[1]/dif:Contact_Address,
153                   $DIF/dif:Data_Center/dif:Personnel[1]/dif:Contact_Address/dif:City,
154                   $DIF/dif:Data_Center/dif:Personnel[1]/dif:Contact_Address/dif:Postal_Code,
155                   $DIF/dif:Data_Center/dif:Personnel[1]/dif:Email)
156        else(),
157       
158     
159      (:
160      NOTE: this is the datestamp of the dif=>iso conversion
161      :)
162      element gmd:dateStamp {
163         
164          element gco:DateTime {data($thisDateTime)}             
165         
166      },     
167      (: ************* metadataStandardName & version******************* :)
168      (:
169      NOTE: this is the name of the standard we have converted dif TO i.e. ndg_isoStub
170      :)
171      element gmd:metadataStandardName {
172          element gco:CharacterString { string('NDG_StubISO19139')}
173      },
174      element gmd:metadataStandardVersion {
175          element gco:CharacterString { string('v0.2')}
176      }, 
177     
178    (: ISO dataset identification info etc :)   
179    element gmd:identificationInfo {
180   
181        (: Dataset name :)
182        element gmd:MD_DataIdentification {
183            element gmd:citation {
184           
185                (: This function handles ALL date types - see publicationCreationDates var :)               
186                isolib:CI_Citation($DIF/dif:Entry_Title,$publicationCreationDates,$DIF/dif:Entry_ID,$DIF/dif:Data_Center/dif:Data_Center_URL)
187               
188                },
189                element gmd:abstract {
190                    element gco:CharacterString {
191                        data ($DIF/dif:Summary)
192                     }
193                 },
194                 
195                 (: more pointOfContact here - go through types required and whats likely to be in the BODC/BGS/BAS DIF's :)
196                 (: originator :) (:data($DIF/dif:Data_Set_Citation[1]/dif:Dataset_Creator):)
197                 if  (exists($DIF/dif:Data_Set_Citation/dif:Dataset_Creator)) then
198                     for $originator in $DIF/dif:Data_Set_Citation
199                     return
200                        isolib:pointOfContact (data($originator/dif:Dataset_Creator), 
201                       string(''),string(''),
202                       string('originator'),
203                       string(''),
204                       $originator/dif:Dataset_Creator,
205                       string(''),
206                      string(''),
207                      string('')
208                   )
209                else (),
210               
211                (: data pointOfContact - go through all Personnel, but don't need to be as fussy as in the metadataPointOfContact in the initial contact element :)
212                 
213               
214
215              (: **************** ISO_Topic_Category ***********************:)
216     
217      (: This is a direct translation from the relevant dif element :)
218      if (exists($DIF/dif:ISO_Topic_Category)) then
219     
220          for $ISO_Topic_Category in $DIF/dif:ISO_Topic_Category
221          return
222              element gmd:topicCategory {
223                  element gmd:MD_TopicCategoryCode {
224                      data ($ISO_Topic_Category)
225                      }
226                   }
227         
228      else (),
229             
230       
231     
232      (: ************* Keyword **********************:)
233      if (exists ($DIF/dif:Keyword)) then
234          for $keyword in $DIF/dif:Keyword
235          return         
236                element gmd:descriptiveKeywords {
237                    element gmd:MD_Keywords {
238                        element gmd:keyword {
239                            element gco:CharacterString { data($keyword) }
240                        }
241                    }
242                }
243    else (),
244   
245    (: if sensor name is in the dif, record this as a keyword too  :)
246    if (exists($DIF/dif:Sensor_Name)) then
247        for $keyword in $DIF/dif:Sensor_Name
248        return
249            element gmd:descriptiveKeywords {
250                    element gmd:MD_Keywords {
251                        element gmd:keyword {
252                            element gco:CharacterString { data($keyword/dif:Short_Name) }
253                        }
254                    }
255               }
256    else (),
257
258
259                       (:/gmd:descriptiveKeywords:)
260             
261      (: ************* /Keyword **********************:)
262     
263      (: ************* Parameters **********************:)
264     
265      (: NERC DMS update - record parameters as keywords - part of better conversion  :)
266      if (exists ($DIF/dif:Parameters)) then
267          for $Parameters in $DIF/dif:Parameters
268          return
269              element gmd:descriptiveKeywords {
270                element gmd:MD_Keywords {
271                    element gmd:keyword {
272                        if (exists($Parameters/ns0:Detailed_Variable)) then
273                            element gco:CharacterString { data($Parameters/ns0:Detailed_Variable) }
274                        else if (exists($Parameters/ns0:Variable)) then
275                            element gco:CharacterString { data($Parameters/ns0:Variable) }
276                        else ()
277                    }
278                   
279                    (: Leave out the thesaurus name bit for now - no actual info provided in DIF and no date info which is mandatory :)
280                    (: ,
281                    element gmd:thesaurusName {                   
282                       
283                       (: needs a date, but no relevant date in the dif to use.. :)
284                       isolib:CI_Citation(concat(data($Parameters/ns0:Category), string(" (Data Provider DIF Category Value)")),string(''),string(""),string(""))
285                    }:)
286                }
287        } else (),
288           
289     
290       (: ************* /Parameters **********************:)
291     
292      (:If any space or time elements in original dif then must put in the gmd:extent element  - remember this is "stub" iso so doesnt have to be valid:)
293        if (exists($DIF/dif:Spatial_Coverage) or exists($DIF/dif:Paleo_Temporal_Coverage) or exists($DIF/dif:Location) or exists($DIF/dif:Temporal_Coverage)) then
294       
295                element gmd:extent {
296                  element gmd:EX_Extent {
297                 
298                  (: Pull out Location Name info too if its there :)
299                  if (exists($DIF/dif:Location)) then
300                      for $loc in $DIF/dif:Location
301                      return
302                          element gmd:geographicElement {
303                              element gmd:EX_GeographicDescription {
304                                  if (exists($loc/dif:Location_Name) and exists($loc/dif:Detailed_Location)) then
305                                      element gmd:MD_Identifier {
306                                          data(concat($loc/dif:Location_Name,": ",$loc/dif:Detailed_Location))
307                                      }
308                                   else
309                                       element gmd:MD_Identifier {
310                                           data ($loc/dif:Location_Name)
311                                      }
312                              }
313                          }
314                  else (),
315                 
316                  (: Spatial Information - if its there... :)     
317                  if (exists($DIF/dif:Spatial_Coverage)  or exists($DIF/dif:Location))  then
318     
319                      for $boundingbox in $DIF/dif:Spatial_Coverage[exists(dif:Northernmost_Latitude)
320                        and exists(dif:Southernmost_Latitude)
321                        and exists(dif:Easternmost_Longitude)
322                        and exists(dif:Westernmost_Longitude)]
323                     return
324                 
325                      element gmd:geographicElement {
326                          element gmd:EX_GeographicBoundingBox {                     
327                             
328                              element gmd:westBoundLongitude {
329                                  element gco:Decimal {
330                                      data(inputParse:fix-coord($boundingbox/dif:Westernmost_Longitude))
331                                   }
332                                },
333                                element gmd:eastBoundLongitude {
334                                  element gco:Decimal {
335                                      data(inputParse:fix-coord($boundingbox/dif:Easternmost_Longitude))
336                                   }
337                                },
338                                element gmd:southBoundLatitude {
339                                  element gco:Decimal {
340                                      data(inputParse:fix-coord($boundingbox/dif:Southernmost_Latitude))
341                                   }
342                                },
343                                 element gmd:northBoundLatitude {
344                                  element gco:Decimal {
345                                      data(inputParse:fix-coord($boundingbox/dif:Northernmost_Latitude))
346                                   }
347                                }
348                               }
349                              }  (: /gmd:geographicElement:)
350                              else (),
351                             
352                              (: temporal info - if it exists :)
353                              if (exists($DIF/dif:Temporal_Coverage) or exists($DIF/dif:Paleo_Temporal_Coverage) or exists($DIF/dif:Chronostratigraphic_Unit)) then
354                              for $temporalcoverage in $DIF/dif:Temporal_Coverage[exists(dif:Start_Date)]
355                              return
356                              element  gmd:temporalElement {                   
357                                    element gmd:EX_TemporalExtent {
358                                        element gmd:extent {
359                                            element gml:TimePeriod {
360                                            (: Note in ISO19139 schemas both start and end elements must be there even if data for only one... :)
361                                                element gml:beginPosition {
362                                                    string($temporalcoverage/dif:Start_Date)
363                                                },
364                                                element gml:endPosition {
365                                                    string($temporalcoverage/dif:Stop_Date)
366                                                }
367                                            }
368                                    }                                 
369                               },                                                           
370                             for $paleotemporalcoverage in $DIF/dif:Paleo_Temporal_Coverage[exists(dif:Paleo_Start_Date)]
371                             return
372                             element  gmd:temporalElement {                   
373                                    element gmd:EX_TemporalExtent {
374                                        element gmd:extent {
375                                            element gml:TimePeriod {
376                                            (: Note in ISO19139 schemas both start and end elements must be there even if data for only one... :)
377                                                element gml:beginPosition {
378                                                    string($paleotemporalcoverage/dif:Paleo_Start_Date)
379                                                },
380                                                element gml:endPosition {
381                                                    string($paleotemporalcoverage/dif:Paleo_Stop_Date)
382                                                }
383                                            }
384                                    }                                 
385                               }                             
386                             }                             
387                             } (: /gmd:temporalElement :)                             
388                             else ()                 
389                            }                             
390                } (: /gmd:extent :)       
391       else ()       
392       }(: /MD_DataIdentification :)
393      },     (: /gmd:identificationInfo  :)
394     
395       (: ***** distributionInfo ****:)     
396      (:
397      This is to hold Parameters and Related_URL
398     
399      07/11/10 - NOTE - MEDIN/DMS also states that the dataset distributor must also  be in distributionInfo - for ease and lack of codelists transcribe DIF/Data_Center straight into role of distributor
400     
401      :)
402      element distributionInfo {
403              element gmd:MD_Distribution {
404                  element gmd:distributionFormat {
405                      attribute gco:nilReason {"inapplicable"} (: According to MEDIN docs this element needed for ISO19115 compliancy :)
406                  }, (:/gmd/distributionFormat :)
407                 
408                  (: Distributor contact info :)
409                  if (exists($DIF/dif:Data_Center)) then
410                      for $DC in $DIF/dif:Data_Center
411                      return
412                          element gmd:MD_Distributor {
413                              element gmd:distributorContact {
414                                  isolib:pointOfContact (data($DC/dif:Data_Center_Name/dif:Short_Name),
415                                  $DC/dif:Personnel[1]/dif:Role,string(''),
416                                  string('distributor'),
417                                  $DC/dif:Personnel[1]/dif:Phone,
418                                  $DC/dif:Personnel[1]/dif:Contact_Address,
419                                  $DC/dif:Personnel[1]/dif:Contact_Address/dif:City,
420                                  $DC/dif:Personnel[1]/dif:Contact_Address/dif:Postal_Code,
421                                  $DC/dif:Personnel[1]/dif:Email)                     
422                      }                 
423                  }
424                  else (),
425                 
426                  if (exists ($DIF/dif:Parameters) or exists ($DIF/dif:Related_URL)) then
427           
428                 
429                  (:
430                     Deal with online resources now - dif:Related_URL - NOTE: currently handle services in this way until we can resolve the srv namespace issue and schema (MEDIN docs p15)
431                  :)
432                 
433                  (: first pull out any online resource from dif citation elements :)
434                  if (exists($DIF/dif:Data_Set_Citation/dif:Online_Resource)) then
435                      for $Related_URL in $DIF/dif:Data_Set_Citation
436                      return
437                          isolib:transferOptions ($Related_URL/dif:Online_Resource, string('Dataset Citation Online Resource'), string('Online Resource'), string('information'))
438                  else (),
439                 
440                  (: Data Center home page :)
441                  if (exists($DIF/dif:Data_Center)) then
442                      for $Related_URL in $DIF/dif:Data_Center
443                      return
444                          isolib:transferOptions ($Related_URL/dif:Data_Center_URL, string('Data Center Online Resource'), string('Data Center Page'), string('information'))
445                  else (),
446                 
447                   if (exists ($DIF/dif:Related_URL)) then
448                      for $Related_URL in $DIF/dif:Related_URL
449                       return
450                           (:isolib:transferOptions ($url as xs:string, $contentType as xs:string, $description as xs:string, $onlineFunctionCode as xs:string):)
451                           
452                           (: note - for dif conversions not really possible to pull out data download easily, so for now classify everything as information :)
453                           isolib:transferOptions ($Related_URL/dif:URL, $Related_URL/dif:URL_Content_Type, $Related_URL/dif:Description, string('information'))
454                           
455                    else ()
456                     
457                (: /distributionInfo :)
458        else ()   
459         }               
460               }
461      } (: /MD_Metadata:)
462   
463
464
Note: See TracBrowser for help on using the repository browser.