source: ndgCommon/trunk/ndg/common/xmldb/xquery/atom2NERCiso.xq @ 7958

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

Update the xq to generate Gemini compliant iso metadata - various updates but should produce output that can validate agaianst the Gemini2 schematron. Should also work for UKSSDC data too.

Line 
1(: CEDA ATOM to NERC Discovery Metadata Standard conversion :)
2
3(: Converts to DMS v0.6 October 2010:)
4
5(:
6Steve Donegan, CEDA RALSpace, 20/10/2010
7
807/02/11: Update conversions to better 0.7+ DMS and to take into account updated ATOM content as part of CEDA DSR procedures (note 1)
922/08/11: Update so can validate in the interim against the Gemini2 schematron.  Note requires changes to imported isoUtilities and also differentiates between
10                gml namespaces for atom (old) and DMS (new -"3.2").  Also added support for new NERC keywords.  Note guidance states that emails are non-nillable so must
11                ensure emails are always provided - in thise case the ceda helpdesk address
12
13Notes:
14    1. Note georss and gml namespaces changed to match those present in CEDA ATOMs in bora.badc.rl.ac.uk eXist database
15   
16:)
17(: eXist library :)
18import module namespace isolib='http://ndg.nerc.ac.uk/xquery/lib/iso_utilities' at 'xmldb:exist:///db/xquery/lib/Utilities/isoUtilities_xquery_lib.xquery';
19
20declare default element namespace 'http://www.isotc211.org/2005/gmd';
21
22declare namespace atom = 'http://www.w3.org/2005/Atom';
23declare namespace moles="http://ndg.nerc.ac.uk/schema/moles2beta";
24declare namespace f='http://ndg.nerc.ac.uk/moles/localfunctions';
25declare namespace georss = "http://www.georss.org/georss/10";
26declare namespace fn = "http://www.w3.org/2005/02/xpath-functions";
27declare namespace xhtml="http://www.w3.org/1999/xhtml";
28
29(: need the dif namespace as we are picking up organisationInfo from dif based record currently in Bora db :)
30declare namespace dif = 'http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/';
31
32(: other NS we need to produce the NERC  ISO :)
33declare namespace gmd='http://www.isotc211.org/2005/gmd';
34declare namespace xsi='http://www.w3.org/2001/XMLSchema-instance';
35declare namespace gco='http://www.isotc211.org/2005/gco';
36declare namespace gmx='http://www.isotc211.org/2005/gmx';
37declare namespace gml='http://www.opengis.net/gml/3.2';
38declare namespace xlink='http://www.w3.org/1999/xlink';
39
40(: atom uses the old gml namespace so use this when pulling gml elements from atom :)
41declare namespace gml_atom='http://www.opengis.net/gml' ;
42
43
44(: Keep this in official lib version
45declare variable $targetCollection as xs:string := '/db/atoms/Published';
46declare variable $deploymentsDir as xs:string := '/deployments';
47declare variable $dataEntitiesDir as xs:string := '/data_entities';
48declare variable $repositoryIdentifier as xs:string := 'badc.nerc.ac.uk';
49declare variable $localIdentifier as xs:string := 'badc.nerc.ac.uk__ATOM__dataent_active';
50declare variable $dptTerm as xs:string := 'DPTTerm';
51declare variable $obsTerm as xs:string :=  'OBSTerm';
52declare variable $activityTerm as xs:string :=  'ACTIVITYTerm';
53declare variable $uriTerm as xs:string :=  'URITerm';
54declare variable $granuleTerm as xs:string :=  'GranuleTerm';
55:)
56
57
58(: Define the name of the metadata standard to be used in converted document :)
59declare variable $MetadataStandardName as xs:string := 'NERC profile of ISO19115:2003';
60declare variable $MetadataStandardVersion as xs:string := '1.0';
61
62(: This should match the values used in the ingester and the dpws i.e. version 1 = NERC_DMS_0.7 :)
63declare variable $MetadataStandardCEDAPrefix as xs:string := 'NERC_DMS_0.7';
64
65(: CEDA eXist directory containing the data center organisation DIF snippets :)
66declare variable $organisationInfoDir as xs:string := '/db/atoms/resources';
67
68(: Development use only  BADC
69declare variable $targetCollection as xs:string := '/db/atoms/published/';
70declare variable $repositoryIdentifier as xs:string := 'badc.nerc.ac.uk';
71declare variable $localIdentifier as xs:string := 'dataent_12233057970926779'; :)
72
73(: Development use only  NEODC
74declare variable $targetCollection as xs:string := '/db/atoms/published/';
75declare variable $repositoryIdentifier as xs:string := 'neodc.nerc.ac.uk';
76declare variable $localIdentifier as xs:string := 'dataent_11658383444211836'; :)
77
78(: Development use only  UKSSDC
79declare variable $targetCollection as xs:string := '/db/atoms/published/';
80declare variable $repositoryIdentifier as xs:string := 'ukssdc.ac.uk';
81declare variable $localIdentifier as xs:string := 'DE_4be56b6c-ec01-11df-9327-00e081470265';  :)
82
83(:Production use only :)
84declare variable $targetCollection as xs:string := 'TargetCollection';
85declare variable $repositoryIdentifier as xs:string := 'RepositoryID';
86declare variable $localIdentifier as xs:string := 'RepositoryID__ATOM__LocalID$';
87
88declare variable $dptTerm as xs:string := 'DPT - NOT YET SET UP/None/DPT';
89declare variable $obsTerm as xs:string :=  'OBS - NOT YET SET UP/None/OBS';
90declare variable $activityTerm as xs:string :=  'Activity - NOT YET SET UP/None/ACTIVITY';
91declare variable $granuleTerm as xs:string :=  'GRAN - NOT YET SET UP/None/GRANULE';
92declare variable $deploymentTerm as xs:string := 'NOT YET SET UP/None/Deployment';
93declare variable $uriTerm as xs:string :=  'URI';
94
95(: These two are unlikely to change :)
96declare variable $dataEntitiesDir as xs:string := 'data_entities';
97declare variable $deploymentsDir as xs:string := 'deployments';
98declare variable $deploymentDataDir as xs:string := 'deployment_data';
99
100(:declare variable $atomCollection as xs:string := concat('TargetCollection', $dataEntitiesDir, '/', 'RepositoryID'); :)
101declare variable $atomCollection as xs:string := concat($targetCollection, $dataEntitiesDir, '/', $repositoryIdentifier    );
102
103declare variable $currentDate as xs:string := substring(current-date() cast as xs:string,1,10);
104
105for $DE in collection($atomCollection)/atom:entry[matches(atom:id, $localIdentifier)]
106
107(:sort out complex variables here as easier to do here than embedded in the xQuery! :)
108
109(: set unique identifier as a variable :)   
110let $identifier := concat(string($DE/moles:entity/moles:molesISO/moles:providerID),':',$MetadataStandardCEDAPrefix,':', tokenize(string($DE/atom:id), '__ATOM__')[2])
111
112(: extract the CEDA Data Center ID :)
113let $cedaIdentifier := $DE/moles:entity/moles:molesISO/moles:providerID
114
115(:define string variable for publication and creation dates comprised of comma delimited list from ATOM elements:)
116let $publicationCreationDates := concat(data($DE/atom:published),"=",string('publication'),",",data($DE/moles:entity/moles:molesISO/moles:created),"=",string("creation"))
117
118return
119
120element gmd:MD_Metadata {
121   
122    element gmd:fileIdentifier {
123        element gco:CharacterString {
124            (: for CEDA purposes use main unique resource identifier here - element 6
125            concat(string($DE/moles:entity/moles:molesISO/moles:providerID),':NERC_v0.6:', tokenize(string($DE/atom:id), '__ATOM__')[2]):)
126            data($identifier)
127        }       
128     },
129     
130     (:Metadata_Language element 29:)
131     element gmd:language {
132     
133         (: TODO: CEDA supports some iso elements in atom, but needs provision for codelist values.  In this case "eng" :)
134         element gmd:LanguageCode {
135             attribute codeList {'http://www.loc.gov/standards/iso639-2/php/code_list.php'},
136             attribute codeListValue {'eng'},
137             data($DE/moles:entity/moles:molesISO/moles:metadataLanguage)         
138         }
139     },
140     
141     (: Resource Type element 4 :)
142     element gmd:hierarchyLevel {
143         element gmd:MD_ScopeCode {         
144             attribute codeList {'http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#MD_ScopeCode'},
145             attribute codeListValue {'series'},
146             string('series')
147         
148         }
149     },
150
151    (: Element 22 Responsible Party - Metadata point of contact.  For CEDA purposes this will be the relevent helpdesk contact :)
152   
153     (: TODO: get this info from ATOM :)
154   
155    element gmd:contact
156    {
157        (:isolib:CI_ResponsibleParty(string("CEDA"), element individualName {string("")}, element positionName{string("CEDA Data Scientist")}, element role {string("pointOfContact")}, element phone {string("01235 778123")}, element addressLine {string("RALSpace, HSIC, Rutherford Appleton Laboratory")}, element city {string("Didcot")}, element postCode {string("OX11 0QX")}, element email{string("ceda@stfc.ac.uk")}):)
158        isolib:cedaDataCenter(string("pointOfContact"), $organisationInfoDir, $cedaIdentifier)
159    },
160   
161    (: Date of update of metadata - Element 26 :)
162    (: For CEDA this translates to the timestamp of the last update in the MOLES db, rather than the datestamp of the application of this conversion... WHICH means moles:updated:)
163    element gmd:dateStamp {
164        element gco:DateTime {
165            replace(string($DE/atom:updated),"Z","")
166        }
167    },
168   
169    (: Metadata Standard Name - Element  27 :)
170    (: For CEDA, this means the version of the NERC Discovery Metadata Standard this conversion is mapped to :)
171    element gmd:metadataStandardName {
172        element gco:CharacterString { data($MetadataStandardName)}
173    },
174   
175    (: Metadata Standard Version - Element 28 :)
176    element gmd:metadataStandardVersion {
177        element gco:CharacterString { data($MetadataStandardVersion)}
178    },
179   
180    (: Spatial Reference System - Element 15 :)
181    (: TODO: does CEDA need to include this in MOLES database? :)
182    element gmd:referenceSystemInfo {
183        element gmd:MD_ReferenceSystem {
184            element gmd:referenceSystemIdentifier {
185                element gmd:RS_Identifier {
186                    element gmd:code {
187                        (: TODO: find correct code! :)
188                        element gco:CharacterString { string("urn:ogc:def:crs:EPSG::27700")}
189                    }
190                }
191            }
192        }
193    },
194   
195    (: identificationInfo :)
196    element gmd:identificationInfo {
197        element gmd:MD_DataIdentification {
198            element gmd:citation {
199           
200                (: NOTE following elements handled by CI_Citation function :)
201           
202                (: Resource Title - Element 1 :)
203                (: Temporal Reference Date - Element 16 :)
204                (: TODO: check CEDA ATOM publication date has the same definition :)
205                (:Publication - Element 16.2 :)
206                (:Creation - Element 16.4 :)
207                (: Identifier - Element 6 :)
208                isolib:CI_Citation(data($DE/atom:title),$publicationCreationDates,$identifier,$DE/moles:entity/moles:molesISO/moles:providerID)
209               
210            },
211           
212            (: Abstract - Element 3 :)
213            element gmd:abstract {
214                element gco:CharacterString {data($DE/atom:summary)}                   
215            },
216           
217            (: Responsible party - Element 22 :)
218           
219            (: TODO: CEDA will need to better delineate this info as may need "originator" in addition to "dataPointOfContact" & metadataPointOfContact :)
220           
221            (:TODO: for CEDA purposes is organisationName sufficient?  Depends on type of pointOfContact as well as whats available
222           
223            UPDATE 08/02/11: If responsibleParties element present in the ATOM then use this to put in a ceda "data curator" pointOfContact -- can always add more via editor
224           
225            :)
226            if (exists($DE/moles:entity/moles:molesISO/moles:responsibleParties)) then
227           
228                for $responsibleParties in $DE/moles:entity/moles:molesISO/moles:responsibleParties/moles:responsibleParty
229               
230                let $name:=$responsibleParties/moles:name
231                let $uri:=$responsibleParties/moles:uri
232                let $role:=$responsibleParties/moles:role
233               
234                return
235                if (contains($name,"badc")) then
236               
237                    (: Mapping from ATOM title "Data Curator"... - shouldnt this be codelisted..?  :)
238                    if ($role = "Data Curator") then
239                        element gmd:pointOfContact {
240                            isolib:cedaDataCenter(string("custodian"), $organisationInfoDir, $name)
241                         }
242                     else ()
243                else ()
244                   
245            else (),
246           
247            (:originator:
248           
249            UPDATE (07/02/11): CEDA now collecting this in ATOm editor albeit only a name and url/email address - but this is all we have at the moment
250           
251            :)
252           
253            if (exists($DE/atom:author)) then
254           
255                for $author in $DE/atom:author
256               
257                    let $name:= $DE/atom:author/atom:name
258                    let $contact:=$DE/atom:author/atom:email
259                   
260                    return
261           
262                        (: Where only name supplied just supply empty text until we can get it factored in :)
263                       
264                        (: where an email is supplied.. format appropriate call to function :)
265                       
266                        element gmd:pointOfContact {
267                            isolib:CI_ResponsibleParty($name, element individualName {string("")}, element positionName{string("")}, element role {string("Originator")}, element phone {string("")}, element addressLine {string("")}, element city {string("")}, element postCode {string("")}, element email{string($contact)})
268                       
269                    }
270            else (),
271
272   
273         
274            (:
275            element gmd:pointOfContact
276            {               
277                (:isolib:CI_ResponsibleParty(string("CEDA"), element individualName {string("")}, element positionName{string("CEDA Data Scientist")}, element role {string("originator")}, element phone {string("01235 778123")}, element addressLine {string("RALSpace, HSIC, Rutherford Appleton Laboratory")}, element city {string("Didcot")}, element postCode {string("OX11 0QX")}, element email{string("ceda@stfc.ac.uk")}):)
278                isolib:cedaDataCenter(string("originator"), $organisationInfoDir, $cedaIdentifier)
279            },
280            :)
281            (:resourceMaintenance - Element # :)
282           
283            (:TODO: CEDA needs to record this resourceMaintenance info plus other INSPIRE related stuff HARDCODE for now! :)
284            (:DONE: CEDA now using values mapped to codelist and placed in $DE/moles:entity/moles:molesISO/moles:updateFrequency :)
285            element gmd:resourceMaintenance {
286                element gmd:MD_MaintenanceInformation {
287                    element gmd:maintenanceAndUpdateFrequency {
288                        element gmd:MD_MaintenanceFrequencyCode {
289                            attribute codeList {'http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#MD_MaintenanceFrequencyCode'},
290                            attribute codeListValue {data($DE/moles:entity/moles:molesISO/moles:updateFrequency)},
291                            data($DE/moles:entity/moles:molesISO/moles:updateFrequency)                         
292                        }                   
293                    }
294                }
295            },
296           
297            (: Data Format :- Element #:)
298            (:TODO: need to get CEDA to evaluate this properly - codelist/vocab? 
299           
300            UPDATE (11/02/11) : can pull format from the atom:content xhtml section  BUT this is a restricted list from http://vocab.ndg.nerc.ac.uk/term/M010/-but its a cr@p list.
301           
302            :)
303           
304            (: this one is pulled from the CEDA ATOM :)
305              for $divContent in $DE/atom:content
306                let $content := isolib:extractAtomContent(string("cedacat:formats"),$divContent)
307                return
308                    if (string-length($content) > 0) then
309                     
310                        element gmd:resourceFormat {
311                            element gmd:MD_Format {
312                                element gmd:name {
313                                    element gco:CharacterString { string($content) }
314                                },
315                                element gmd:version {
316                                    attribute gco:nilReason {"inapplicable"}
317                                }
318                            }
319                        }
320                    else (), (: optional element so only fill if theres summat there :)
321           
322            (: Keywords - Element 11 :)
323           
324            (: Ensure NERC_DDC is in there :)
325           
326            (: TODO: CEDA/NERC - is this keyword in a vocab or codelist?/
327           
328            UPDATE 23/08/2011: Use the standardised keyword (eventually the pipeline should add this at the MOLES vN level
329           
330            :)
331           
332            element gmd:descriptiveKeywords {
333                    element gmd:MD_Keywords {
334                        element gmd:keyword{
335                            element gmx:Anchor {
336                                attribute xlink:href {string("http://vocab.ndg.nerc.ac.uk/term/N010/current/NDGO0003")},                               
337                                string("Natural Environment Research Council Designated Data Centres")
338                            }                           
339                        }
340                    }
341                },
342           
343            (: Vertical Extent - Element 14:)
344           
345            (: TODO - CEDA have to implement vertical extent keywords - must take from L131 list on NDG vocab server.  :)
346                     
347            (: if vertical extent present - pull this through for now, notwithstanding whether its on the L131 list or not.. :)
348            for $keyword in $DE/moles:entity/moles:molesISO/moles:verticalExtent           
349            return
350                element gmd:descriptiveKeywords {
351                    element gmd:MD_Keywords {
352                        element gmd:keyword{
353                            element gmx:Anchor {
354                                attribute xlink:href {string("http://vocab.ndg.nerc.ac.uk/term/L131/3")},
355                               
356                                (: use the unknown vocab reference.. this may show up on the portal as an error! :)
357                                attribute xlink:title {string("UK")},
358                                data($keyword)
359                            }                           
360                        }
361                    }
362                },
363               
364            (: depending on whether BADC or NEODC record, add in some hardcoded VE keywords for good measure!:)
365             
366             if (contains($cedaIdentifier,"badc")) then           
367               element gmd:descriptiveKeywords {
368                    element gmd:MD_Keywords {
369                        element gmd:keyword{
370                            element gmx:Anchor {
371                                attribute xlink:href {string("http://vocab.ndg.nerc.ac.uk/term/L131/3")},
372                                attribute xlink:title {string("AT")},
373                                string("atmosphere")
374                            }                           
375                        }
376                    }
377                }           
378            else (),           
379           
380            if (contains($cedaIdentifier,"neodc")) then           
381                element gmd:descriptiveKeywords {
382                    element gmd:MD_Keywords {
383                        element gmd:keyword{
384                            element gmx:Anchor {
385                                attribute xlink:href {string("http://vocab.ndg.nerc.ac.uk/term/L131/3")},
386                                attribute xlink:title {string("UK")},
387                                string("unknown")
388                            }                           
389                        }
390                    }
391                }           
392            else (),
393           
394            (: INSPIRE keywords :)
395           
396            (: TODO: CEDA - need to have info on INSPIRE themes available in the CEDA MOLES db - hardwire for now
397           
398            Update: freetext field available in editor now - still need to map this to a vocab...
399           
400            PROBLEM 14/02/11: lack of suitable GEMET keywords for CEDA datasets/themes?
401           
402            :)
403           
404            if (contains($cedaIdentifier,"badc")) then           
405               element gmd:descriptiveKeywords {
406                element gmd:MD_Keywords {
407                    element gmd:keyword {
408                        element gco:CharacterString { string("Atmospheric conditions") }
409                    },
410                    element gmd:thesaurusName {                   
411                        isolib:CI_Citation(string('GEMET - INSPIRE themes, version 1.0'),concat($currentDate,"=",string('publication')),string(""),string(""))
412                    }
413                }
414            }
415            else (),
416           
417            if (contains($cedaIdentifier,"badc")) then           
418               element gmd:descriptiveKeywords {
419                element gmd:MD_Keywords {
420                    element gmd:keyword {
421                        element gco:CharacterString { string("Meteorological geographical features") }
422                    },
423                    element gmd:thesaurusName {                   
424                        isolib:CI_Citation(string('GEMET - INSPIRE themes, version 1.0'),concat($currentDate,"=",string('publication')),string(""),string(""))
425                    }
426                }
427            }
428            else (),
429           
430            if (contains($cedaIdentifier,"neodc")) then           
431               element gmd:descriptiveKeywords {
432                element gmd:MD_Keywords {
433                    element gmd:keyword {
434                        element gco:CharacterString { string("Orthoimagery") }
435                    },
436                    element gmd:thesaurusName {                   
437                        isolib:CI_Citation(string('GEMET - INSPIRE themes, version 1.0'),concat($currentDate,"=",string('publication')),string(""),string(""))
438                    }
439                }
440            }
441            else (),
442           
443           
444            (: TODO: CEDA - need to properly quantify keywords/parameters to actual vocabs.  For now map category attribute "label" to  keyword value in gmx:anchor and the scheme to xlink:href attritubte and term to title. 
445            follow medin example for nerc harvesting keyword.  This seriously needs tidying up
446           
447            UPDATE (07/02/11): do not take any definitions where the term="NULL" or if the word "ATOM" is in the Category, or "0" as all nonsensical and relict from previous mungings in the old pipeline
448           
449            :)
450            for $keyword in $DE/atom:category
451            let $term:=$keyword/@term
452            let $label:=$keyword/@label
453            let $scheme:=$keyword/@scheme
454            return
455            if (not(contains($term,"NULL")) and not(contains($term,"ATOM")) and not($term="0")) then
456                element gmd:descriptiveKeywords {
457                    element gmd:MD_Keywords {
458                        element gmd:keyword{
459                            element gmx:Anchor {
460                                attribute xlink:href {data($scheme)},
461                                attribute xlink:title {data($term)},
462                                data($label)
463                            }                           
464                        }
465                    }
466                }
467             else (),
468           
469            (: Conditions applying to access and use - Element 21 :)
470            (: TODO: CEDA doesnt record this in ATOM & its Mandatory.  Hardcode for now
471           
472            UPDATE 11/02/11: This information is now held in the atom:content XHTML - use new function to extract text and place it here..
473           
474            NOTE - similar info to element 20 accessConstraints and all lumped together in the atom:content so use the same here, but if none is detected put "no conditions apply"
475                   
476            :)
477         
478              for $divContent in $DE/atom:content
479                let $content := isolib:extractAtomContent(string("cedacat:access-restricted"),$divContent)
480                return
481                    if (string-length($content) > 0) then
482                                         
483                        element gmd:resourceConstraints {
484                            element gmd:MD_Constraints {
485                                element gmd:useLimitation {
486                                    element gco:CharacterString {string("Restrictions Apply")}
487                                }
488                            }
489                        }                   
490                   
491                    else
492                   
493                       (: Can't detect any access restrictions so to be safe use otherRestrictions :)
494           
495                        (: element 20 first :)
496                        element gmd:resourceConstraints {
497                            element gmd:MD_Constraints {
498                                element gmd:useLimitation {
499                                    element gco:CharacterString {string("no conditions apply")}
500                                }
501                            }
502                        },
503           
504            (: Limitations on Public Access - Element 20 :)           
505            (: TODO: CEDA doesnt record this in ATOM - & its Mandatory.  Hardcode for now
506           
507            UPDATE 11/02/11: This information is now held in the atom:content XHTML - use new function to extract text and place it here..
508           
509            (operation notes: if text found, then stick in an appropriate codeList value codeList value -
510           
511            :)
512           
513            for $divContent in $DE/atom:content
514                let $content := isolib:extractAtomContent(string("cedacat:access-restricted"),$divContent)
515                return
516                    if (string-length($content) > 0) then
517                                     
518                        (: element 21 now :)
519                        element gmd:resourceConstraints {
520                            element gmd:MD_LegalConstraints {
521                                element gmd:accessConstraints {
522                                    element gmd:MD_RestrictionCode {
523                           
524                                     (:TODO: CEDA will need link to this codelist for this element :)
525                                    attribute codeList {'http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#MD_RestrictionCode'},
526                                    attribute codeListValue {'otherRestrictions'},
527                                    string("otherRestrictions")                       
528                                    }
529                                },
530                                element gmd:otherConstraints {
531                                    element gco:CharacterString { string($content)}
532                                }
533                            }
534                        }
535                   
536                    else
537                   
538                       (: Can't detect any access restrictions so to be safe use otherRestrictions :)
539                               
540                        element gmd:resourceConstraints {
541                            element gmd:MD_LegalConstraints {
542                                element gmd:accessConstraints {
543                                    element gmd:MD_RestrictionCode {
544                           
545                                     (:TODO: CEDA will need link to this codelist for this element :)
546                                    attribute codeList {'http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#MD_RestrictionCode'},
547                                    attribute codeListValue {'otherRestrictions'},
548                                    string("otherRestrictions")                       
549                                    }
550                                },
551                                element gmd:otherConstraints {
552                                    element gco:CharacterString { string("Please refer to the dataset homepage for further information")}
553                                }
554                            }
555                        },
556           
557            (: Spatial Resolution - Element 18 :)
558           
559            (: TODO: CEDA doesnt record this in ATOM yet & its Mandatory: Hardcode for now to value of "0"...
560           
561            UPDATE - CEDA now recording these values as open text - Should be M where known for INSPIRE...
562           
563            :)
564           
565            element gmd:spatialResolution {
566                element gmd:MD_Resolution {
567                    element gmd:distance {
568                        if (exists($DE/moles:entity/moles:molesISO/moles:spatialResolution)) then
569                        element gmd:distance {
570                       
571                            (: TODO: CEDA only has open text field - will need to get the correct EPSG code for this.. hardcode for now.. :)
572                            attribute uom {"urn:ogc:def:uom:EPSG::9001"},
573                            data($DE/moles:entity/moles:molesISO/moles:spatialResolution)
574                        }
575                        else
576                        element gmd:distance {
577                            attribute gco:nilReason {"inapplicable"}
578                        }
579                    }
580                }           
581            },
582           
583            (: Resource Langauge - Element 8 :)
584            (:TODO: CEDA will need to include this element if any textual resource for the dataset - hardcode to english for now :)
585            element gmd:language {
586                element gmd:LanguageCode {
587                    attribute codeList {'http://www.loc.gov/standards/iso639-2/php/code_list.php'},
588                    attribute codeListValue {'eng'},
589                    string("English")
590                }
591            },
592           
593            (: Topic Category - Element 9:)
594            (:TODO: CEDA will also need to include this information as mandatory for datasets.  For now, hardcoded to "Geoscientific Information"
595           
596            UPDATE - still needs to be hardcoded as npt supported by DSR round1 editor updates, but use badc/neodc specific categories that are better descriptive of data
597           
598            :)
599           
600            if (contains($cedaIdentifier,"badc")) then           
601                element gmd:topicCategory {
602                    element gmd:MD_TopicCategoryCode {string("climatologyMeteorologyAtmosphere")}
603                }               
604            else (),           
605           
606            if (contains($cedaIdentifier,"neodc")) then           
607                element gmd:topicCategory {
608                    element gmd:MD_TopicCategoryCode {string("imageryBaseMapsEarthCover")}
609                }               
610            else (),
611            element gmd:topicCategory {
612                    element gmd:MD_TopicCategoryCode {string("environment")}
613                },
614           
615           
616            (: TODO: Many CEDA datasets don't have boundingBox info - MAndatory for compliancy..
617           
618            UPDATE (16/02/11): Note one extent tag for each SEPARATE spatial or temporal extents
619           
620            :)
621             element gmd:extent {
622                element gmd:EX_Extent {
623               
624                     (:Extent - Bounding Box - Element 12 (note difference from an actual extent - i.e. ICES sea areas:)
625               
626                    if (exists($DE/georss:where)) then
627                        for $boundingBox in $DE/georss:where
628                        return
629                       
630                            if ((tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:lowerCorner), ' ')[1]="0.0") and (tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:upperCorner), ' ')[1]="0.0") and (tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:lowerCorner), ' ')[2]="0.0") and (tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:upperCorner), ' ')[2]="0.0")) then
631                           
632                                element gmd:geographicElement {
633                                element gmd:EX_GeographicBoundingBox {                                                   
634                                    element gmd:westBoundLongitude {
635                                        element gco:Decimal {
636                                            string("-180")
637                                        }
638                                    },
639                                    element gmd:eastBoundLongitude {
640                                        element gco:Decimal {
641                                            string("180")
642                                        }
643                                    },
644                                    element gmd:southBoundLatitude {
645                                        element gco:Decimal {
646                                            string("-90")
647                                        }
648                                    },
649                                    element gmd:northBoundLatitude {
650                                        element gco:Decimal {
651                                            string("90")
652                                        }
653                                    }
654                                }
655                            }
656                            else
657                       
658                            element gmd:geographicElement{
659                                element gmd:EX_GeographicBoundingBox {                                                   
660                                    element gmd:westBoundLongitude {
661                                        element gco:Decimal {
662                                             if (ends-with(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:lowerCorner), ' ')[1],".")) then                                                 
663                                                 data(substring-before(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:lowerCorner), ' ')[1],"."))
664                                             else
665                                                data(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:lowerCorner), ' ')[1])
666                                        }
667                                    },
668                                    element gmd:eastBoundLongitude {
669                                        element gco:Decimal {
670                                            if (ends-with(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:upperCorner), ' ')[1],".")) then                                                 
671                                                 data(substring-before(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:upperCorner), ' ')[1],"."))
672                                             else
673                                                data(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:upperCorner), ' ')[1])
674                                       
675                                        }
676                                    },
677                                    element gmd:southBoundLatitude {
678                                        element gco:Decimal {
679                                            if (ends-with(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:lowerCorner), ' ')[2],".")) then                                                 
680                                                 data(substring-before(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:lowerCorner), ' ')[2],"."))
681                                             else
682                                                data(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:lowerCorner), ' ')[2])
683                                       
684                                        }
685                                    },
686                                    element gmd:northBoundLatitude {
687                                        element gco:Decimal {
688                                            if (ends-with(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:upperCorner), ' ')[2],".")) then                                                 
689                                                 data(substring-before(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:upperCorner), ' ')[2],"."))
690                                             else
691                                                data(tokenize(string($boundingBox/gml_atom:Envelope/gml_atom:upperCorner), ' ')[2])
692                                 
693                                        }
694                                    }
695                                }
696                            }
697                        else
698                        element gmd:geographicElement {
699                                element gmd:EX_GeographicBoundingBox {                                                   
700                                    element gmd:westBoundLongitude {
701                                        element gco:Decimal {
702                                            string("-180")
703                                        }
704                                    },
705                                    element gmd:eastBoundLongitude {
706                                        element gco:Decimal {
707                                            string("180")
708                                        }
709                                    },
710                                    element gmd:southBoundLatitude {
711                                        element gco:Decimal {
712                                            string("-90")
713                                        }
714                                    },
715                                    element gmd:northBoundLatitude {
716                                        element gco:Decimal {
717                                            string("90")
718                                        }
719                                    }
720                                }
721                            }
722                          }
723                        },
724                       
725                        (: Temporal Reference - Element 16.1 :)
726                        (: TODO: CEDA - mandatory element yet not all dataEntities have this recorded...
727                            AND - ATOM doesnt distinguish a single date as either start or end!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  blimey.
728                           
729                            UPDATE: NERC DMS now specifiies that "nilReason" be specified where data is unavailable.  Following code now deals with crappy ATOM date handling                           
730                        :)
731                     element gmd:extent {
732                      element gmd:EX_Extent {
733                        element gmd:temporalElement {
734                            element gmd:EX_TemporalExtent {
735                                if (exists($DE/moles:temporalRange)) then
736                                    for $dates in $DE/moles:temporalRange
737                                   
738                                    (:Need to isolate distinct start and end dates here, and if nothing in them detect and enter gco:nilReason="unknown" -all this down to damn stupid way of handling temporal data in ATOM!:)
739                                    let $isRange:=contains(string($dates),"/")
740                                    let $rangeStringLength:=string-length(string($dates))
741                                    let $rangeStartDate:=tokenize(string($dates), '/')[1]
742                                    let $rangeEndDate:=tokenize(string($dates), '/')[2]
743                                   
744                                    return                                       
745                                        element gmd:extent {
746                                           
747                                                if ($isRange) then
748                                                    element gml:TimePeriod {
749                                                       
750                                                        if (string-length($rangeStartDate) >1) then                                                             
751                                                            element gml:beginPosition {
752                                                                 data ($rangeStartDate)
753                                                             }
754                                                        else
755                                                            element gml:beginPosition {
756                                                                attribute gco:nilReason {"unknown"}
757                                                            },
758                                                         
759                                                         if (string-length($rangeEndDate) >1) then                                                             
760                                                            element gml:endPosition {
761                                                                 data ($rangeEndDate)
762                                                             }
763                                                        else
764                                                            element gml:endPosition {
765                                                                attribute gco:nilReason {"unknown"}
766                                                            }                                                 
767                                                        }
768                                                       
769                                                 else
770                                                     (:if not a range, then the atom editor only allows begin position - but check that a value is entered as might be blank!:)
771                                                     if ($rangeStringLength > 1) then
772                                                         element gml:TimePeriod {                                           
773                                                            element gml:beginPosition {
774                                                                data ($dates)
775                                                            },                                               
776                                                            element gml:endPosition {
777                                                                attribute gco:nilReason {"unknown"}
778                                                            }
779                                                         }
780                                                     else
781                                                         element gml:TimePeriod {                                           
782                                                             element gml:beginPosition {
783                                                                   attribute gco:nilReason {"unknown"}
784                                                            },                                               
785                                                              element gml:endPosition {
786                                                                   attribute gco:nilReason {"unknown"}
787                                                            }
788                                                        }
789                                           
790                                        }
791                                else ()
792                            }                       
793                        }
794                    }                       
795             }, (: /extent:)
796         
797         
798          (: supplementalInformation - can pull some info out of the atom:content and put here..:)
799         
800          for $divContent in $DE/atom:content
801                let $content := isolib:extractAtomContent(string("cedacat:citation"),$divContent)
802                return
803                    if (string-length($content) > 0) then
804         
805                      element gmd:supplementalInformation {
806                        element gco:CharacterString {string($content)}
807                      }
808                   else ()
809             
810          }
811    },  (: /identificationInfo :)
812   
813    (: distributionInfo :)
814    element gmd:distributionInfo {
815        element gmd:MD_Distribution {
816   
817            (: The ISO 19115 Constraints require this element! :)
818            element gmd:distributionFormat {
819                attribute gco:nilReason {"inapplicable"}       
820            },
821       
822            (: Responsible Party - Element 22 - Mandatory for datasets! NOTE role=distributor so ok to hardwire as CEDA :)
823            element gmd:distributor {
824                element gmd:MD_Distributor{
825                    element gmd:distributorContact {                                               
826                        isolib:cedaDataCenter(string("distributor"), $organisationInfoDir, $cedaIdentifier)
827                    }
828                }           
829            },
830           
831            (: Resource Locator - Element 5.  NOTE for NERC onlineResource must be provided for datasets:)
832           
833            (: TODO: For CEDA purposes - ensure link to dataset browser is explicitly included in info is in ATOM - indicated by attribute val "Data Directory" :)
834           
835            (:TODO: CEDA - must specifiy correct choice of onlineresource from vocab/codelist - hardwired for "download" right now. :
836           
837            UPDATE Feb 2011 - CEDA Discovery records must only have data download and dataset homepage links (i.e. get rid of all deployment links etc)
838           
839            :)
840           
841            for $link in $DE/atom:link
842                let $url:= $link/@href
843                let $relation:= $link/@rel
844                let $title:= $link/@title
845                return
846                   
847                    (: Check for ATOM codeList values and convert as necessary..   :)                 
848                    if (contains(string($relation),string("DOWNLOAD"))) then
849                 
850                         isolib:transferOptions (string($url), string(replace(string($relation),"NOT YET SET UP/","")), string($title), string("download"))
851                         
852                    else if ($relation = "self") then
853                        (: For NERC DMS, download must only be used where online data is actually available.  So, until CEDA can link to the correct codelist and get these vals into the ATOM we must do this.. :)
854                        isolib:transferOptions (string($url), string("CEDA Dataset Homepage"), string($title), string("information"))
855                    else ()
856                   }   
857        }, (: /distributionInfo :)
858       
859        (: Lineage and INSPIRE conformity elements - Element 25 :)
860        element gmd:dataQualityInfo {
861            element gmd:DQ_DataQuality {
862               
863                (: Scope -required by ISO19115 :)
864                element gmd:scope {
865                    element gmd:DQ_Scope {
866                        element gmd:level {
867                            element gmd:MD_ScopeCode {
868                       
869                                (: TODO: as part of CEDA creep towards INSPIRE conformity, this codelist should be listed:)
870                                attribute codeList {'http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#MD_ScopeCode'},
871                                attribute codeListValue {'dataset'},
872                                string("dataset")
873                            }
874                        }
875                    }
876                },
877               
878                (: Lineage - Element 17 :)
879               
880                (: TODO: CEDA : doesnt currently record this information, so hardwire for now - BUT can use ATOM content with CEDA basic strapline  :)
881                (: DONE - CEDA now records in ATOM this info in moles:entity/moles:molesISO.  ALSO some ATOMS have "quality" info - string this together with lineage info :)
882                if (exists($DE/moles:entity/moles:molesISO/moles:lineage))
883                then
884                element gmd:lineage {
885                    element gmd:LI_Lineage {
886                        element gmd:statement {
887                            element gco:CharacterString {
888                                if (exists($DE/moles:entity/moles:molesISO/moles:quality)) then
889                                    concat(data($DE/moles:entity/moles:molesISO/moles:lineage)," ; ",data($DE/moles:entity/moles:molesISO/moles:quality))
890                                else
891                                    data($DE/moles:entity/moles:molesISO/moles:lineage)
892                            }
893                        }
894                    }
895                }               
896                else
897                (: return standard bit if lineage not available on this atom :)
898                element gmd:lineage {
899                    element gmd:LI_Lineage {
900                        element gmd:statement {
901                            element gco:CharacterString {
902                                data(concat(string("This Dataset has been acquired by CEDA and is hosted by agreement from the data originator.")," ",$DE/atom:content/xhtml:div))
903                            }
904                        }
905                    }
906                }
907               
908               
909            }       
910        } (: /dataQualityInfo :)
911   
912    }
913   
914
Note: See TracBrowser for help on using the repository browser.