geonode-pycsw 3.0.0b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. geonode_pycsw-3.0.0b2.dist-info/METADATA +73 -0
  2. geonode_pycsw-3.0.0b2.dist-info/RECORD +382 -0
  3. geonode_pycsw-3.0.0b2.dist-info/WHEEL +5 -0
  4. geonode_pycsw-3.0.0b2.dist-info/entry_points.txt +2 -0
  5. geonode_pycsw-3.0.0b2.dist-info/licenses/LICENSE.txt +26 -0
  6. geonode_pycsw-3.0.0b2.dist-info/top_level.txt +1 -0
  7. pycsw/__init__.py +33 -0
  8. pycsw/core/__init__.py +29 -0
  9. pycsw/core/admin.py +703 -0
  10. pycsw/core/config.py +621 -0
  11. pycsw/core/etree.py +43 -0
  12. pycsw/core/formats/__init__.py +29 -0
  13. pycsw/core/formats/fmt_json.py +69 -0
  14. pycsw/core/log.py +71 -0
  15. pycsw/core/metadata.py +1996 -0
  16. pycsw/core/pygeofilter_evaluate.py +83 -0
  17. pycsw/core/repository.py +941 -0
  18. pycsw/core/schemas/ogc/cat/csw/3.0/_wrapper.xsd +14 -0
  19. pycsw/core/schemas/ogc/cat/csw/3.0/cswAll.xsd +33 -0
  20. pycsw/core/schemas/ogc/cat/csw/3.0/cswCommon.xsd +71 -0
  21. pycsw/core/schemas/ogc/cat/csw/3.0/cswGetCapabilities.xsd +80 -0
  22. pycsw/core/schemas/ogc/cat/csw/3.0/cswGetDomain.xsd +146 -0
  23. pycsw/core/schemas/ogc/cat/csw/3.0/cswGetRecordById.xsd +58 -0
  24. pycsw/core/schemas/ogc/cat/csw/3.0/cswGetRecords.xsd +391 -0
  25. pycsw/core/schemas/ogc/cat/csw/3.0/cswHarvest.xsd +95 -0
  26. pycsw/core/schemas/ogc/cat/csw/3.0/cswTransaction.xsd +187 -0
  27. pycsw/core/schemas/ogc/cat/csw/3.0/cswUnHarvest.xsd +77 -0
  28. pycsw/core/schemas/ogc/cat/csw/3.0/rec-dcmes.xsd +245 -0
  29. pycsw/core/schemas/ogc/cat/csw/3.0/rec-dcterms.xsd +101 -0
  30. pycsw/core/schemas/ogc/cat/csw/3.0/record.xsd +170 -0
  31. pycsw/core/schemas/ogc/csw/2.0.2/CSW-discovery.xsd +494 -0
  32. pycsw/core/schemas/ogc/csw/2.0.2/CSW-publication.xsd +242 -0
  33. pycsw/core/schemas/ogc/csw/2.0.2/rec-dcmes.xsd +199 -0
  34. pycsw/core/schemas/ogc/csw/2.0.2/rec-dcterms.xsd +94 -0
  35. pycsw/core/schemas/ogc/csw/2.0.2/record.xsd +138 -0
  36. pycsw/core/schemas/ogc/filter/1.1.0/expr.xsd +67 -0
  37. pycsw/core/schemas/ogc/filter/1.1.0/filter.xsd +265 -0
  38. pycsw/core/schemas/ogc/filter/1.1.0/filterCapabilities.xsd +171 -0
  39. pycsw/core/schemas/ogc/filter/1.1.0/sort.xsd +46 -0
  40. pycsw/core/schemas/ogc/filter/2.0/_wrapper.xsd +5 -0
  41. pycsw/core/schemas/ogc/filter/2.0/expr.xsd +44 -0
  42. pycsw/core/schemas/ogc/filter/2.0/filter.xsd +396 -0
  43. pycsw/core/schemas/ogc/filter/2.0/filterAll.xsd +23 -0
  44. pycsw/core/schemas/ogc/filter/2.0/filterCapabilities.xsd +286 -0
  45. pycsw/core/schemas/ogc/filter/2.0/query.xsd +70 -0
  46. pycsw/core/schemas/ogc/filter/2.0/sort.xsd +49 -0
  47. pycsw/core/schemas/ogc/gml/3.1.1/base/basicTypes.xsd +278 -0
  48. pycsw/core/schemas/ogc/gml/3.1.1/base/coordinateOperations.xsd +789 -0
  49. pycsw/core/schemas/ogc/gml/3.1.1/base/coordinateReferenceSystems.xsd +429 -0
  50. pycsw/core/schemas/ogc/gml/3.1.1/base/coordinateSystems.xsd +408 -0
  51. pycsw/core/schemas/ogc/gml/3.1.1/base/coverage.xsd +451 -0
  52. pycsw/core/schemas/ogc/gml/3.1.1/base/dataQuality.xsd +129 -0
  53. pycsw/core/schemas/ogc/gml/3.1.1/base/datums.xsd +484 -0
  54. pycsw/core/schemas/ogc/gml/3.1.1/base/defaultStyle.xsd +454 -0
  55. pycsw/core/schemas/ogc/gml/3.1.1/base/dictionary.xsd +137 -0
  56. pycsw/core/schemas/ogc/gml/3.1.1/base/direction.xsd +72 -0
  57. pycsw/core/schemas/ogc/gml/3.1.1/base/dynamicFeature.xsd +115 -0
  58. pycsw/core/schemas/ogc/gml/3.1.1/base/feature.xsd +199 -0
  59. pycsw/core/schemas/ogc/gml/3.1.1/base/geometryAggregates.xsd +430 -0
  60. pycsw/core/schemas/ogc/gml/3.1.1/base/geometryBasic0d1d.xsd +602 -0
  61. pycsw/core/schemas/ogc/gml/3.1.1/base/geometryBasic2d.xsd +213 -0
  62. pycsw/core/schemas/ogc/gml/3.1.1/base/geometryComplexes.xsd +141 -0
  63. pycsw/core/schemas/ogc/gml/3.1.1/base/geometryPrimitives.xsd +1609 -0
  64. pycsw/core/schemas/ogc/gml/3.1.1/base/gml.xsd +22 -0
  65. pycsw/core/schemas/ogc/gml/3.1.1/base/gmlBase.xsd +294 -0
  66. pycsw/core/schemas/ogc/gml/3.1.1/base/grids.xsd +76 -0
  67. pycsw/core/schemas/ogc/gml/3.1.1/base/measures.xsd +200 -0
  68. pycsw/core/schemas/ogc/gml/3.1.1/base/observation.xsd +96 -0
  69. pycsw/core/schemas/ogc/gml/3.1.1/base/referenceSystems.xsd +211 -0
  70. pycsw/core/schemas/ogc/gml/3.1.1/base/temporal.xsd +332 -0
  71. pycsw/core/schemas/ogc/gml/3.1.1/base/temporalReferenceSystems.xsd +251 -0
  72. pycsw/core/schemas/ogc/gml/3.1.1/base/temporalTopology.xsd +186 -0
  73. pycsw/core/schemas/ogc/gml/3.1.1/base/topology.xsd +459 -0
  74. pycsw/core/schemas/ogc/gml/3.1.1/base/units.xsd +170 -0
  75. pycsw/core/schemas/ogc/gml/3.1.1/base/valueObjects.xsd +361 -0
  76. pycsw/core/schemas/ogc/gml/3.1.1/smil/smil20-language.xsd +117 -0
  77. pycsw/core/schemas/ogc/gml/3.1.1/smil/smil20.xsd +234 -0
  78. pycsw/core/schemas/ogc/gml/3.2.1/basicTypes.xsd +268 -0
  79. pycsw/core/schemas/ogc/gml/3.2.1/coordinateOperations.xsd +525 -0
  80. pycsw/core/schemas/ogc/gml/3.2.1/coordinateReferenceSystems.xsd +373 -0
  81. pycsw/core/schemas/ogc/gml/3.2.1/coordinateSystems.xsd +297 -0
  82. pycsw/core/schemas/ogc/gml/3.2.1/coverage.xsd +292 -0
  83. pycsw/core/schemas/ogc/gml/3.2.1/datums.xsd +287 -0
  84. pycsw/core/schemas/ogc/gml/3.2.1/defaultStyle.xsd +453 -0
  85. pycsw/core/schemas/ogc/gml/3.2.1/deprecatedTypes.xsd +1133 -0
  86. pycsw/core/schemas/ogc/gml/3.2.1/dictionary.xsd +90 -0
  87. pycsw/core/schemas/ogc/gml/3.2.1/direction.xsd +84 -0
  88. pycsw/core/schemas/ogc/gml/3.2.1/dynamicFeature.xsd +109 -0
  89. pycsw/core/schemas/ogc/gml/3.2.1/feature.xsd +94 -0
  90. pycsw/core/schemas/ogc/gml/3.2.1/geometryAggregates.xsd +197 -0
  91. pycsw/core/schemas/ogc/gml/3.2.1/geometryBasic0d1d.xsd +277 -0
  92. pycsw/core/schemas/ogc/gml/3.2.1/geometryBasic2d.xsd +124 -0
  93. pycsw/core/schemas/ogc/gml/3.2.1/geometryComplexes.xsd +95 -0
  94. pycsw/core/schemas/ogc/gml/3.2.1/geometryPrimitives.xsd +846 -0
  95. pycsw/core/schemas/ogc/gml/3.2.1/gml.xsd +20 -0
  96. pycsw/core/schemas/ogc/gml/3.2.1/gmlBase.xsd +185 -0
  97. pycsw/core/schemas/ogc/gml/3.2.1/grids.xsd +64 -0
  98. pycsw/core/schemas/ogc/gml/3.2.1/measures.xsd +68 -0
  99. pycsw/core/schemas/ogc/gml/3.2.1/observation.xsd +95 -0
  100. pycsw/core/schemas/ogc/gml/3.2.1/referenceSystems.xsd +70 -0
  101. pycsw/core/schemas/ogc/gml/3.2.1/temporal.xsd +269 -0
  102. pycsw/core/schemas/ogc/gml/3.2.1/temporalReferenceSystems.xsd +189 -0
  103. pycsw/core/schemas/ogc/gml/3.2.1/temporalTopology.xsd +119 -0
  104. pycsw/core/schemas/ogc/gml/3.2.1/topology.xsd +386 -0
  105. pycsw/core/schemas/ogc/gml/3.2.1/units.xsd +162 -0
  106. pycsw/core/schemas/ogc/gml/3.2.1/valueObjects.xsd +205 -0
  107. pycsw/core/schemas/ogc/ogcapi/records/part1/1.0/ogcapi-records-1.yaml +932 -0
  108. pycsw/core/schemas/ogc/ows/1.0.0/ows19115subset.xsd +222 -0
  109. pycsw/core/schemas/ogc/ows/1.0.0/owsAll.xsd +20 -0
  110. pycsw/core/schemas/ogc/ows/1.0.0/owsCommon.xsd +155 -0
  111. pycsw/core/schemas/ogc/ows/1.0.0/owsDataIdentification.xsd +112 -0
  112. pycsw/core/schemas/ogc/ows/1.0.0/owsExceptionReport.xsd +67 -0
  113. pycsw/core/schemas/ogc/ows/1.0.0/owsGetCapabilities.xsd +108 -0
  114. pycsw/core/schemas/ogc/ows/1.0.0/owsOperationsMetadata.xsd +161 -0
  115. pycsw/core/schemas/ogc/ows/1.0.0/owsServiceIdentification.xsd +55 -0
  116. pycsw/core/schemas/ogc/ows/1.0.0/owsServiceProvider.xsd +46 -0
  117. pycsw/core/schemas/ogc/ows/1.1.0/ows19115subset.xsd +236 -0
  118. pycsw/core/schemas/ogc/ows/1.1.0/owsAll.xsd +23 -0
  119. pycsw/core/schemas/ogc/ows/1.1.0/owsCommon.xsd +158 -0
  120. pycsw/core/schemas/ogc/ows/1.1.0/owsContents.xsd +87 -0
  121. pycsw/core/schemas/ogc/ows/1.1.0/owsDataIdentification.xsd +128 -0
  122. pycsw/core/schemas/ogc/ows/1.1.0/owsDomainType.xsd +280 -0
  123. pycsw/core/schemas/ogc/ows/1.1.0/owsExceptionReport.xsd +77 -0
  124. pycsw/core/schemas/ogc/ows/1.1.0/owsGetCapabilities.xsd +113 -0
  125. pycsw/core/schemas/ogc/ows/1.1.0/owsGetResourceByID.xsd +52 -0
  126. pycsw/core/schemas/ogc/ows/1.1.0/owsInputOutputData.xsd +60 -0
  127. pycsw/core/schemas/ogc/ows/1.1.0/owsManifest.xsd +125 -0
  128. pycsw/core/schemas/ogc/ows/1.1.0/owsOperationsMetadata.xsd +141 -0
  129. pycsw/core/schemas/ogc/ows/1.1.0/owsServiceIdentification.xsd +61 -0
  130. pycsw/core/schemas/ogc/ows/1.1.0/owsServiceProvider.xsd +48 -0
  131. pycsw/core/schemas/ogc/ows/2.0/ows19115subset.xsd +364 -0
  132. pycsw/core/schemas/ogc/ows/2.0/owsAdditionalParameters.xsd +114 -0
  133. pycsw/core/schemas/ogc/ows/2.0/owsAll.xsd +29 -0
  134. pycsw/core/schemas/ogc/ows/2.0/owsCommon.xsd +275 -0
  135. pycsw/core/schemas/ogc/ows/2.0/owsContents.xsd +163 -0
  136. pycsw/core/schemas/ogc/ows/2.0/owsDataIdentification.xsd +202 -0
  137. pycsw/core/schemas/ogc/ows/2.0/owsDomainType.xsd +388 -0
  138. pycsw/core/schemas/ogc/ows/2.0/owsExceptionReport.xsd +126 -0
  139. pycsw/core/schemas/ogc/ows/2.0/owsGetCapabilities.xsd +220 -0
  140. pycsw/core/schemas/ogc/ows/2.0/owsGetResourceByID.xsd +83 -0
  141. pycsw/core/schemas/ogc/ows/2.0/owsInputOutputData.xsd +98 -0
  142. pycsw/core/schemas/ogc/ows/2.0/owsManifest.xsd +181 -0
  143. pycsw/core/schemas/ogc/ows/2.0/owsOperationsMetadata.xsd +234 -0
  144. pycsw/core/schemas/ogc/ows/2.0/owsServiceIdentification.xsd +98 -0
  145. pycsw/core/schemas/ogc/ows/2.0/owsServiceProvider.xsd +64 -0
  146. pycsw/core/schemas/w3c/1999/xlink.xsd +271 -0
  147. pycsw/core/schemas/w3c/2001/xml.xsd +287 -0
  148. pycsw/core/util.py +552 -0
  149. pycsw/oaipmh.py +311 -0
  150. pycsw/ogc/__init__.py +29 -0
  151. pycsw/ogc/api/__init__.py +28 -0
  152. pycsw/ogc/api/oapi.py +558 -0
  153. pycsw/ogc/api/records.py +1414 -0
  154. pycsw/ogc/api/templates/_base.html +76 -0
  155. pycsw/ogc/api/templates/collection.html +44 -0
  156. pycsw/ogc/api/templates/collections.html +45 -0
  157. pycsw/ogc/api/templates/conformance.html +21 -0
  158. pycsw/ogc/api/templates/exception.html +8 -0
  159. pycsw/ogc/api/templates/item.html +228 -0
  160. pycsw/ogc/api/templates/items.html +337 -0
  161. pycsw/ogc/api/templates/landing_page.html +27 -0
  162. pycsw/ogc/api/templates/openapi.html +58 -0
  163. pycsw/ogc/api/templates/queryables.html +50 -0
  164. pycsw/ogc/api/templates/stac_items.html +173 -0
  165. pycsw/ogc/api/templates/static/favicon.ico +0 -0
  166. pycsw/ogc/api/templates/static/logo-horizontal.png +0 -0
  167. pycsw/ogc/api/templates/static/logo-vertical-darkbg.png +0 -0
  168. pycsw/ogc/api/util.py +252 -0
  169. pycsw/ogc/csw/__init__.py +29 -0
  170. pycsw/ogc/csw/cql.py +133 -0
  171. pycsw/ogc/csw/csw2.py +2042 -0
  172. pycsw/ogc/csw/csw3.py +2193 -0
  173. pycsw/ogc/fes/__init__.py +29 -0
  174. pycsw/ogc/fes/fes1.py +433 -0
  175. pycsw/ogc/fes/fes2.py +451 -0
  176. pycsw/ogc/gml/__init__.py +29 -0
  177. pycsw/ogc/gml/gml3.py +240 -0
  178. pycsw/ogc/gml/gml32.py +243 -0
  179. pycsw/opensearch.py +857 -0
  180. pycsw/plugins/__init__.py +29 -0
  181. pycsw/plugins/outputschemas/__init__.py +31 -0
  182. pycsw/plugins/outputschemas/atom.py +143 -0
  183. pycsw/plugins/outputschemas/datacite.py +375 -0
  184. pycsw/plugins/outputschemas/dif.py +213 -0
  185. pycsw/plugins/outputschemas/fgdc.py +180 -0
  186. pycsw/plugins/outputschemas/gm03.py +240 -0
  187. pycsw/plugins/profiles/__init__.py +29 -0
  188. pycsw/plugins/profiles/apiso/__init__.py +29 -0
  189. pycsw/plugins/profiles/apiso/apiso.py +757 -0
  190. pycsw/plugins/profiles/apiso/schemas/ogc/csw/2.0.2/profiles/apiso/1.0.0/apiso.xsd +13 -0
  191. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gco/basicTypes.xsd +429 -0
  192. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gco/gco.xsd +12 -0
  193. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gco/gcoBase.xsd +61 -0
  194. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/applicationSchema.xsd +42 -0
  195. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/citation.xsd +275 -0
  196. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/constraints.xsd +106 -0
  197. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/content.xsd +188 -0
  198. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/dataQuality.xsd +554 -0
  199. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/distribution.xsd +202 -0
  200. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/extent.xsd +205 -0
  201. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/freeText.xsd +122 -0
  202. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/gmd.xsd +12 -0
  203. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/identification.xsd +348 -0
  204. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/maintenance.xsd +86 -0
  205. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/metadataApplication.xsd +175 -0
  206. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/metadataEntity.xsd +70 -0
  207. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/metadataExtension.xsd +99 -0
  208. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/portrayalCatalogue.xsd +36 -0
  209. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/referenceSystem.xsd +100 -0
  210. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/spatialRepresentation.xsd +237 -0
  211. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/basicTypes.xsd +267 -0
  212. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/coordinateOperations.xsd +639 -0
  213. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/coordinateReferenceSystems.xsd +526 -0
  214. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/coordinateSystems.xsd +401 -0
  215. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/coverage.xsd +462 -0
  216. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/datums.xsd +342 -0
  217. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/dictionary.xsd +129 -0
  218. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/direction.xsd +80 -0
  219. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/dynamicFeature.xsd +142 -0
  220. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/feature.xsd +215 -0
  221. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/geometryAggregates.xsd +216 -0
  222. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/geometryBasic0d1d.xsd +304 -0
  223. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/geometryBasic2d.xsd +123 -0
  224. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/geometryComplexes.xsd +89 -0
  225. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/geometryPrimitives.xsd +892 -0
  226. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/gml.xsd +14 -0
  227. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/gmlBase.xsd +305 -0
  228. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/grids.xsd +58 -0
  229. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/measures.xsd +167 -0
  230. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/observation.xsd +90 -0
  231. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/referenceSystems.xsd +69 -0
  232. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/temporal.xsd +263 -0
  233. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/temporalReferenceSystems.xsd +183 -0
  234. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/temporalTopology.xsd +124 -0
  235. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/topology.xsd +372 -0
  236. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/units.xsd +156 -0
  237. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/valueObjects.xsd +212 -0
  238. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/catalogues.xsd +112 -0
  239. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/codelistItem.xsd +168 -0
  240. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/crsItem.xsd +1030 -0
  241. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/extendedTypes.xsd +75 -0
  242. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/gmx.xsd +2 -0
  243. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/gmxUsage.xsd +127 -0
  244. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/uomItem.xsd +162 -0
  245. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gsr/gsr.xsd +12 -0
  246. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gsr/spatialReferencing.xsd +24 -0
  247. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gss/geometry.xsd +35 -0
  248. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gss/gss.xsd +12 -0
  249. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gts/gts.xsd +12 -0
  250. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gts/temporalObjects.xsd +34 -0
  251. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/srv/serviceMetadata.xsd +197 -0
  252. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/srv/serviceModel.xsd +220 -0
  253. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/srv/srv.xsd +13 -0
  254. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gco/basicTypes.xsd +431 -0
  255. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gco/gco.xsd +12 -0
  256. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gco/gcoBase.xsd +63 -0
  257. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/applicationSchema.xsd +43 -0
  258. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/citation.xsd +276 -0
  259. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/constraints.xsd +107 -0
  260. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/content.xsd +190 -0
  261. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/dataQuality.xsd +556 -0
  262. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/distribution.xsd +203 -0
  263. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/extent.xsd +206 -0
  264. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/freeText.xsd +123 -0
  265. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/gmd.xsd +12 -0
  266. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/identification.xsd +349 -0
  267. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/maintenance.xsd +87 -0
  268. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/metadataApplication.xsd +176 -0
  269. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/metadataEntity.xsd +71 -0
  270. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/metadataExtension.xsd +100 -0
  271. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/portrayalCatalogue.xsd +37 -0
  272. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/referenceSystem.xsd +101 -0
  273. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/spatialRepresentation.xsd +238 -0
  274. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/catalogues.xsd +113 -0
  275. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/codelistItem.xsd +169 -0
  276. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/crsItem.xsd +1031 -0
  277. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/extendedTypes.xsd +76 -0
  278. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/gmx.xsd +12 -0
  279. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/gmxUsage.xsd +128 -0
  280. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/uomItem.xsd +163 -0
  281. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gsr/gsr.xsd +12 -0
  282. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gsr/spatialReferencing.xsd +25 -0
  283. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gss/geometry.xsd +36 -0
  284. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gss/gss.xsd +12 -0
  285. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gts/gts.xsd +12 -0
  286. pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gts/temporalObjects.xsd +35 -0
  287. pycsw/plugins/profiles/ebrim/__init__.py +29 -0
  288. pycsw/plugins/profiles/ebrim/ebrim.py +174 -0
  289. pycsw/plugins/profiles/ebrim/schemas/ogc/csw/2.0.2/profiles/ebrim/1.0/csw-ebrim-iri.xsd +146 -0
  290. pycsw/plugins/profiles/ebrim/schemas/ogc/csw/2.0.2/profiles/ebrim/1.0/csw-ebrim.xsd +104 -0
  291. pycsw/plugins/profiles/iso19115p3/__init__.py +29 -0
  292. pycsw/plugins/profiles/iso19115p3/iso19115p3.py +854 -0
  293. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cat/1.0/cat.xsd +13 -0
  294. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cat/1.0/catalogues.xsd +53 -0
  295. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cat/1.0/codelistItem.xsd +54 -0
  296. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cat/1.0/crsItem.xsd +181 -0
  297. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cat/1.0/uomItem.xsd +38 -0
  298. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cit/1.0/cit.xsd +7 -0
  299. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cit/1.0/citation.xsd +514 -0
  300. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cit/2.0/cit.xsd +10 -0
  301. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cit/2.0/citation.xsd +523 -0
  302. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gco/1.0/baseTypes2014.xsd +530 -0
  303. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gco/1.0/gco.xsd +16 -0
  304. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gcx/1.0/extendedTypes.xsd +92 -0
  305. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gcx/1.0/extendedTypes_autoFromShapeChange.xsd +60 -0
  306. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gcx/1.0/gcx.xsd +8 -0
  307. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gex/1.0/extent.xsd +241 -0
  308. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gex/1.0/gex.xsd +9 -0
  309. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gmw/1.0/gmlWrapperTypes2014.xsd +159 -0
  310. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gmw/1.0/gmw.xsd +14 -0
  311. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/lan/1.0/lan.xsd +8 -0
  312. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/lan/1.0/language.xsd +140 -0
  313. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mac/1.0/acquisitionInformationImagery.xsd +622 -0
  314. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mac/1.0/mac.xsd +11 -0
  315. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mac/2.0/acquisitionInformationImagery.xsd +590 -0
  316. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mac/2.0/event.xsd +108 -0
  317. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mac/2.0/mac.xsd +10 -0
  318. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mas/1.0/applicationSchema.xsd +61 -0
  319. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mas/1.0/mas.xsd +9 -0
  320. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mcc/1.0/AbstractCommonClasses.xsd +358 -0
  321. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mcc/1.0/commonClasses.xsd +220 -0
  322. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mcc/1.0/mcc.xsd +8 -0
  323. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mco/1.0/constraints.xsd +188 -0
  324. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mco/1.0/mco.xsd +8 -0
  325. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/md1/1.0/md1.xsd +9 -0
  326. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/md1/1.0/metadataWExtendedType.xsd +4 -0
  327. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/md2/1.0/md2.xsd +15 -0
  328. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/md2/1.0/metadataWithExtensions.xsd +4 -0
  329. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mda/1.0/mda.xsd +8 -0
  330. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mda/1.0/metadataApplication.xsd +200 -0
  331. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdb/1.0/mdb.xsd +14 -0
  332. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdb/1.0/metadataBase.xsd +98 -0
  333. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdb/2.0/mdb.xsd +20 -0
  334. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdb/2.0/metadataBase.xsd +102 -0
  335. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mds/1.0/mds.xsd +22 -0
  336. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mds/1.0/metadataDataServices.xsd +4 -0
  337. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdt/1.0/mdt.xsd +13 -0
  338. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdt/1.0/metadataTransfer.xsd +111 -0
  339. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mex/1.0/metadataExtension.xsd +156 -0
  340. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mex/1.0/mex.xsd +8 -0
  341. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mmi/1.0/maintenance.xsd +76 -0
  342. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mmi/1.0/mmi.xsd +8 -0
  343. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mpc/1.0/mpc.xsd +8 -0
  344. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mpc/1.0/portrayalCatalogue.xsd +31 -0
  345. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/1.0/content.xsd +416 -0
  346. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/1.0/contentInformationImagery.xsd +185 -0
  347. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/1.0/mrc.xsd +11 -0
  348. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/2.0/content.xsd +419 -0
  349. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/2.0/contentInformationImagery.xsd +171 -0
  350. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/2.0/mrc.xsd +11 -0
  351. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrd/1.0/distribution.xsd +267 -0
  352. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrd/1.0/mrd.xsd +8 -0
  353. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mri/1.0/identification.xsd +517 -0
  354. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mri/1.0/mri.xsd +9 -0
  355. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/1.0/lineage.xsd +147 -0
  356. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/1.0/lineageImagery.xsd +236 -0
  357. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/1.0/mrl.xsd +9 -0
  358. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/2.0/lineage.xsd +147 -0
  359. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/2.0/lineageImagery.xsd +312 -0
  360. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/2.0/mrl.xsd +11 -0
  361. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrs/1.0/mrs.xsd +8 -0
  362. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrs/1.0/referenceSystem.xsd +47 -0
  363. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/1.0/msr.xsd +10 -0
  364. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/1.0/spatialRepresentation.xsd +375 -0
  365. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/1.0/spatialRepresentationImagery.xsd +119 -0
  366. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/2.0/msr.xsd +15 -0
  367. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/2.0/spatialRepresentation.xsd +381 -0
  368. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/2.0/spatialRepresentationImagery.xsd +120 -0
  369. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/srv/2.0/serviceInformation.xsd +272 -0
  370. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/srv/2.0/srv.xsd +6 -0
  371. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/srv/2.1/serviceInformation.xsd +278 -0
  372. pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/srv/2.1/srv.xsd +6 -0
  373. pycsw/plugins/profiles/profile.py +141 -0
  374. pycsw/plugins/repository/__init__.py +29 -0
  375. pycsw/plugins/repository/odc/__init__.py +29 -0
  376. pycsw/plugins/repository/odc/odc.py +153 -0
  377. pycsw/server.py +938 -0
  378. pycsw/sru.py +217 -0
  379. pycsw/stac/__init__.py +29 -0
  380. pycsw/stac/api.py +571 -0
  381. pycsw/wsgi.py +233 -0
  382. pycsw/wsgi_flask.py +345 -0
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+ # =================================================================
3
+ #
4
+ # Authors: Tom Kralidis <tomkralidis@gmail.com>
5
+ #
6
+ # Copyright (c) 2015 Tom Kralidis
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person
9
+ # obtaining a copy of this software and associated documentation
10
+ # files (the "Software"), to deal in the Software without
11
+ # restriction, including without limitation the rights to use,
12
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ # copies of the Software, and to permit persons to whom the
14
+ # Software is furnished to do so, subject to the following
15
+ # conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27
+ # OTHER DEALINGS IN THE SOFTWARE.
28
+ #
29
+ # =================================================================
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+ # =================================================================
3
+ #
4
+ # Authors: Tom Kralidis <tomkralidis@gmail.com>
5
+ #
6
+ # Copyright (c) 2015 Tom Kralidis
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person
9
+ # obtaining a copy of this software and associated documentation
10
+ # files (the "Software"), to deal in the Software without
11
+ # restriction, including without limitation the rights to use,
12
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ # copies of the Software, and to permit persons to whom the
14
+ # Software is furnished to do so, subject to the following
15
+ # conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27
+ # OTHER DEALINGS IN THE SOFTWARE.
28
+ #
29
+ # =================================================================
30
+
31
+ __all__ = ['atom', 'dif', 'fgdc', 'gm03', 'datacite']
@@ -0,0 +1,143 @@
1
+ # -*- coding: utf-8 -*-
2
+ # =================================================================
3
+ #
4
+ # Authors: Tom Kralidis <tomkralidis@gmail.com>
5
+ #
6
+ # Copyright (c) 2024 Tom Kralidis
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person
9
+ # obtaining a copy of this software and associated documentation
10
+ # files (the "Software"), to deal in the Software without
11
+ # restriction, including without limitation the rights to use,
12
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ # copies of the Software, and to permit persons to whom the
14
+ # Software is furnished to do so, subject to the following
15
+ # conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27
+ # OTHER DEALINGS IN THE SOFTWARE.
28
+ #
29
+ # =================================================================
30
+
31
+ from pycsw.core import util
32
+ from pycsw.core.etree import etree
33
+
34
+ NAMESPACE = 'http://www.w3.org/2005/Atom'
35
+ NAMESPACES = {'atom': NAMESPACE, 'georss': 'http://www.georss.org/georss'}
36
+
37
+ XPATH_MAPPINGS = {
38
+ 'pycsw:Identifier': 'atom:id',
39
+ 'pycsw:Title': 'atom:title',
40
+ 'pycsw:Creator': 'atom:author',
41
+ 'pycsw:Abstract': 'atom:summary',
42
+ 'pycsw:PublicationDate': 'atom:published',
43
+ 'pycsw:Keywords': 'atom:category',
44
+ 'pycsw:Contributor': 'atom:contributor',
45
+ 'pycsw:AccessConstraints': 'atom:rights',
46
+ 'pycsw:Modified': 'atom:updated',
47
+ 'pycsw:Source': 'atom:source',
48
+ }
49
+
50
+ def write_record(result, esn, context, url=None):
51
+ ''' Return csw:SearchResults child as lxml.etree.Element '''
52
+
53
+ typename = util.getqattr(result, context.md_core_model['mappings']['pycsw:Typename'])
54
+
55
+ if esn == 'full' and typename == 'atom:entry':
56
+ # dump record as is and exit
57
+ return etree.fromstring(util.getqattr(result, context.md_core_model['mappings']['pycsw:XML']), context.parser)
58
+
59
+ node = etree.Element(util.nspath_eval('atom:entry', NAMESPACES), nsmap=NAMESPACES)
60
+ node.attrib[util.nspath_eval('xsi:schemaLocation', context.namespaces)] = \
61
+ '%s http://www.kbcafe.com/rss/atom.xsd.xml' % NAMESPACES['atom']
62
+
63
+ # author
64
+ val = util.getqattr(result, context.md_core_model['mappings']['pycsw:Creator'])
65
+ if val:
66
+ author = etree.SubElement(node, util.nspath_eval('atom:author', NAMESPACES))
67
+ etree.SubElement(author, util.nspath_eval('atom:name', NAMESPACES)).text = val
68
+
69
+ # category
70
+ val = util.getqattr(result, context.md_core_model['mappings']['pycsw:Keywords'])
71
+
72
+ if val:
73
+ for kw in val.split(','):
74
+ etree.SubElement(node, util.nspath_eval('atom:category', NAMESPACES), term=kw)
75
+
76
+
77
+ for qval in ['pycsw:Contributor', 'pycsw:Identifier']:
78
+ val = util.getqattr(result, context.md_core_model['mappings'][qval])
79
+ if val:
80
+ etree.SubElement(node, util.nspath_eval(XPATH_MAPPINGS[qval], NAMESPACES)).text = val
81
+ if qval == 'pycsw:Identifier':
82
+ etree.SubElement(node, util.nspath_eval('dc:identifier', context.namespaces)).text = val
83
+
84
+ rlinks = util.getqattr(result, context.md_core_model['mappings']['pycsw:Links'])
85
+ if rlinks:
86
+ for link in util.jsonify_links(rlinks):
87
+ url2 = etree.SubElement(node, util.nspath_eval('atom:link', NAMESPACES), href=link['url'])
88
+
89
+ if link.get('description') is not None:
90
+ url2.attrib['title'] = link['description']
91
+
92
+ if link.get('protocol') is not None:
93
+ url2.attrib['type'] = link['protocol']
94
+
95
+ if link.get('function') is not None:
96
+ url2.attrib['rel'] = link['function']
97
+
98
+ etree.SubElement(node, util.nspath_eval('atom:link', NAMESPACES), href='%s?service=CSW&version=2.0.2&request=GetRepositoryItem&id=%s' % (url, util.getqattr(result, context.md_core_model['mappings']['pycsw:Identifier'])))
99
+
100
+ # atom:title
101
+ el = etree.SubElement(node, util.nspath_eval(XPATH_MAPPINGS['pycsw:Title'], NAMESPACES))
102
+ val = util.getqattr(result, context.md_core_model['mappings']['pycsw:Title'])
103
+ if val:
104
+ el.text =val
105
+
106
+ # atom:updated
107
+ el = etree.SubElement(node, util.nspath_eval(XPATH_MAPPINGS['pycsw:Modified'], NAMESPACES))
108
+ val = util.getqattr(result, context.md_core_model['mappings']['pycsw:Modified'])
109
+ if val:
110
+ el.text =val
111
+ else:
112
+ val = util.getqattr(result, context.md_core_model['mappings']['pycsw:InsertDate'])
113
+ el.text = val
114
+
115
+ for qval in ['pycsw:PublicationDate', 'pycsw:AccessConstraints', 'pycsw:Source', 'pycsw:Abstract']:
116
+ val = util.getqattr(result, context.md_core_model['mappings'][qval])
117
+ if val:
118
+ etree.SubElement(node, util.nspath_eval(XPATH_MAPPINGS[qval], NAMESPACES)).text = val
119
+
120
+ # bbox extent
121
+ val = util.getqattr(result, context.md_core_model['mappings']['pycsw:BoundingBox'])
122
+ bboxel = write_extent(val, context.namespaces)
123
+ if bboxel is not None:
124
+ node.append(bboxel)
125
+
126
+ return node
127
+
128
+ def write_extent(bbox, nsmap):
129
+ ''' Generate BBOX extent '''
130
+
131
+ if bbox is not None:
132
+ try:
133
+ bbox2 = util.wkt2geom(bbox)
134
+ except Exception as err:
135
+ LOGGER.debug(f'Geometry parsing error: {err}')
136
+ return None
137
+ where = etree.Element(util.nspath_eval('georss:where', NAMESPACES))
138
+ envelope = etree.SubElement(where, util.nspath_eval('gml:Envelope', nsmap), srsName='http://www.opengis.net/def/crs/EPSG/0/4326')
139
+ etree.SubElement(envelope, util.nspath_eval('gml:lowerCorner', nsmap)).text = '%s %s' % (bbox2[1], bbox2[0])
140
+ etree.SubElement(envelope, util.nspath_eval('gml:upperCorner', nsmap)).text = '%s %s' % (bbox2[3], bbox2[2])
141
+
142
+ return where
143
+ return None
@@ -0,0 +1,375 @@
1
+ # -*- coding: utf-8 -*-
2
+ # =================================================================
3
+ #
4
+ # - pycsw DataCite output plugin -
5
+ #
6
+ # Authors: Carl-Fredrik Enell <carl-fredrik.enell@eiscat.se>, Paul van Genuchten <genuchten@yahoo.com>
7
+ # Based on pycsw plugins by Tom Kralidis <tomkralidis@gmail.com>
8
+ # DataCite schema follows:
9
+ # https://github.com/inveniosoftware/datacite/blob/master/datacite/schema42.py
10
+ # https://schema.datacite.org/meta/kernel-4.3/example/datacite-example-full-v4.xml
11
+ #
12
+ # This module intends to follow DataCite 4.3
13
+ #
14
+ # PyCSW Copyright (C) 2024 Tom Kralidis
15
+ # Schema Copyright (C) 2016 CERN
16
+ # Schema Copyright (C) 2019 Caltech
17
+ #
18
+ # Permission is hereby granted, free of charge, to any person
19
+ # obtaining a copy of this software and associated documentation
20
+ # files (the "Software"), to deal in the Software without
21
+ # restriction, including without limitation the rights to use,
22
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
23
+ # copies of the Software, and to permit persons to whom the
24
+ # Software is furnished to do so, subject to the following
25
+ # conditions:
26
+ #
27
+ # The above copyright notice and this permission notice shall be
28
+ # included in all copies or substantial portions of the Software.
29
+
30
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
32
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
34
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
35
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
36
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
37
+ # OTHER DEALINGS IN THE SOFTWARE.
38
+ #
39
+ # =================================================================
40
+ from pycsw.core import util
41
+ from pycsw.core.etree import etree
42
+ from os.path import basename
43
+ from datetime import datetime
44
+ import json
45
+ import logging
46
+
47
+ """
48
+ datacite.py
49
+ Output plugin for DataCite 4.3 schema output
50
+ Defines function write_record
51
+ Input: result, esn, context, url (pycsw query results)
52
+ Output: XML etree according to DataCite schema
53
+ """
54
+
55
+ NAMESPACE = 'http://datacite.org/schema/kernel-4'
56
+ NAMESPACES = {'xml': 'http://www.w3.org/XML/1998/namespace',
57
+ 'datacite': NAMESPACE,
58
+ 'oai': 'http://www.openarchives.org/OAI/2.0/'}
59
+ LOGGER = logging.getLogger(__name__)
60
+
61
+ XPATH_MAPPINGS = {
62
+ 'pycsw:Identifier': 'identifier',
63
+ 'pycsw:Date': 'dates/date',
64
+ 'pycsw:Creator': 'creators/creator',
65
+ 'pycsw:Title': 'titles/title',
66
+ 'pycsw:Abstract': 'descriptions/description',
67
+ 'pycsw:Publisher': 'publisher',
68
+ 'pycsw:BoundingBox': 'geoLocations/geoLocation/geoLocationBox',
69
+ 'pycsw:Format': 'formats/format',
70
+ 'pycsw:Language': 'Language',
71
+ 'pycsw:Edition': 'version',
72
+ 'pycsw:PublicationDate': 'dates/date',
73
+ 'pycsw:Keywords': 'subjects/subject',
74
+ 'pycsw:TopicCategory': 'subjects/subject',
75
+ 'pycsw:Themes': 'subjects/subject',
76
+ 'pycsw:Lineage': 'lineage',
77
+ 'pycsw:TempExtent_begin': '',
78
+ 'pycsw:TempExtent_end': '',
79
+ 'pycsw:Contributor': '',
80
+ 'pycsw:AccessConstraints': '',
81
+ 'pycsw:Contacts': '',
82
+ 'pycsw:Links': ''
83
+ }
84
+
85
+
86
+ def write_record(result, esn, context, url=None):
87
+ """
88
+ Main function
89
+ Return csw:SearchResults child as lxml.etree.Element
90
+ """
91
+ typename = util.getqattr(result, context.md_core_model['mappings']['pycsw:Typename'])
92
+ # Check if we already have DataCite formatted metadata
93
+ if esn == 'full' and typename == 'datacite':
94
+ # dump record as is and exit
95
+ return etree.fromstring(util.getqattr(result, context.md_core_model['mappings']['pycsw:XML']), context.parser)
96
+
97
+ # Otherwise build XML tree from available metadata
98
+ node = etree.Element(util.nspath_eval('resource', NAMESPACES))
99
+ node.attrib[util.nspath_eval('xsi:schemaLocation', context.namespaces)] = \
100
+ '%s http://schema.datacite.org/meta/kernel-4.3/metadata.xsd' % NAMESPACE
101
+ # Type
102
+ type = etree.SubElement(node, util.nspath_eval('resourceType', NAMESPACES))
103
+ resTypeGeneral = basename(util.getqattr(result, context.md_core_model['mappings']['pycsw:Type']))
104
+ type.text = resTypeGeneral
105
+
106
+ if resTypeGeneral.lower() in ["dataset","nongeographicdataset","featuretype","transferaggregate","otheraggregate"]:
107
+ resTypeGeneral = "Dataset"
108
+ elif resTypeGeneral.lower() in ["software"]:
109
+ resTypeGeneral = "Software"
110
+ elif resTypeGeneral.lower() in ["collectionSession","fieldSession"]:
111
+ resTypeGeneral = "Event"
112
+ elif resTypeGeneral.lower() in ["service"]:
113
+ resTypeGeneral = "Service"
114
+ elif resTypeGeneral.lower() in ["model"]:
115
+ resTypeGeneral = "Model"
116
+ elif resTypeGeneral.lower() in ["series"]:
117
+ resTypeGeneral = "Collection"
118
+ elif resTypeGeneral.lower() in ["text","document","article"]:
119
+ resTypeGeneral = "Text"
120
+ elif resTypeGeneral.lower() in ["image"]:
121
+ resTypeGeneral = "Image"
122
+ else:
123
+ resTypeGeneral = "Other"
124
+
125
+ assert resTypeGeneral in [
126
+ "Audiovisual",
127
+ "Book",
128
+ "BookChapter",
129
+ "Collection",
130
+ "ComputationalNotebook",
131
+ "ConferencePaper",
132
+ "ConferenceProceeding",
133
+ "DataPaper",
134
+ "Dataset",
135
+ "Dissertation",
136
+ "Event",
137
+ "Image",
138
+ "InteractiveResource",
139
+ "Journal",
140
+ "JournalArticle",
141
+ "Model",
142
+ "OutputManagementPlan",
143
+ "PeerReview",
144
+ "PhysicalObject",
145
+ "Preprint",
146
+ "Report",
147
+ "Service",
148
+ "Software",
149
+ "Sound",
150
+ "Standard",
151
+ "Text",
152
+ "Workflow",
153
+ "Other"
154
+ ]
155
+ type.attrib[util.nspath_eval('resourceTypeGeneral', NAMESPACES)] = resTypeGeneral
156
+
157
+ # Identifier
158
+ ident = etree.SubElement(node, util.nspath_eval('identifier', NAMESPACES))
159
+ ival = util.getqattr(result, context.md_core_model['mappings']['pycsw:Identifier'])
160
+ ident.text = ival
161
+ #Identifier type:
162
+ # NB DOI is mandatory for DataCite proper but we plan to use the schema with other IDs too. Modify as necessary.
163
+ if ival.lower().startswith("doi"):
164
+ idType = "DOI"
165
+ elif ival.lower().startswith("handle"):
166
+ idType = "Handle"
167
+ elif ival.lower().startswith("urn"):
168
+ idType = "URN"
169
+ else:
170
+ idType = "URL"
171
+ ident.attrib[util.nspath_eval('identifierType', NAMESPACES)] = idType or "DOI"
172
+
173
+ # modified
174
+ mod = util.getqattr(result, context.md_core_model['mappings']['pycsw:Date'])
175
+ if mod not in [None, '']:
176
+ dates = etree.SubElement(node, util.nspath_eval('dates', NAMESPACES))
177
+ date = etree.SubElement(dates, util.nspath_eval('date', NAMESPACES))
178
+ date.attrib['dateType'] = 'Updated'
179
+ date.text = mod
180
+
181
+ # Title
182
+ titles = etree.SubElement(node, util.nspath_eval('titles', NAMESPACES))
183
+ tval = util.getqattr(result, context.md_core_model['mappings']['pycsw:Title'])
184
+ title = etree.SubElement(titles, util.nspath_eval('title', NAMESPACES))
185
+ title.attrib[util.nspath_eval("xml:lang", NAMESPACES)]= util.getqattr(result, context.md_core_model['mappings']['pycsw:Language']) or "eng"
186
+ title.text = tval
187
+
188
+ # keywords
189
+ # <subjects><subject xml:lang="eng">example</subject></subjects>
190
+ kwval = util.getqattr(result, context.md_core_model['mappings']['pycsw:Keywords'])
191
+ tcval = util.getqattr(result, context.md_core_model['mappings']['pycsw:TopicCategory'])
192
+ kws = etree.SubElement(node, util.nspath_eval('subjects', NAMESPACES))
193
+ if kwval not in [None, '']:
194
+ # todo: subject per kw
195
+ kw = etree.SubElement(kws, util.nspath_eval('subject', NAMESPACES))
196
+ kw.attrib[util.nspath_eval("xml:lang", NAMESPACES)]= util.getqattr(result, context.md_core_model['mappings']['pycsw:Language']) or "eng"
197
+ kw.text = kwval
198
+ if tcval not in [None, '']:
199
+ kw = etree.SubElement(kws, util.nspath_eval('subject', NAMESPACES))
200
+ kw.attrib['schemaUri'] = 'https://schemas.opengis.net/iso/19139/20070417/resources/codelist/gmxCodelists.xml#MD_TopicCategoryCode'
201
+ kw.text = tcval
202
+ # themes
203
+ # <subjects><subject schemeURI="https://example.com" xml:lang="eng">example</subject></subjects>
204
+ themes = util.getqattr(result, context.md_core_model['mappings']['pycsw:Themes'])
205
+ if themes not in [None, '']:
206
+ try:
207
+ for t in json.loads(themes):
208
+ thesaurus = t.get('thesaurus',{}).get('url', t.get('thesaurus',{}).get('title', ''))
209
+ for k in [c for c in t.get('keywords', []) if c['name'] not in [None, '']]:
210
+ kw = etree.SubElement(kws, util.nspath_eval('subject', NAMESPACES))
211
+ kw.attrib['schemaUri'] = thesaurus
212
+ kw.text = k.get('name')
213
+ except Exception as err:
214
+ LOGGER.exception(f"failed to parse themes json of {themes}: {err}")
215
+
216
+ # publisher, creator, contributor, should have at least 1 creator (use originator else organization else ...)
217
+ cval = util.getqattr(result, context.md_core_model['mappings']['pycsw:Contacts'])
218
+ hasCreator = False # requires at least 1 creator
219
+ creas = etree.SubElement(node, util.nspath_eval('creators', NAMESPACES))
220
+ hasPublisher = False # 1 publisher at most
221
+ if cval not in [None, '', 'null']:
222
+ conts = etree.SubElement(node, util.nspath_eval('contributors', NAMESPACES))
223
+ try:
224
+ for cnt in json.loads(cval):
225
+ try:
226
+ cont = etree.SubElement(conts, util.nspath_eval('contributor', NAMESPACES))
227
+ roleMapping = {
228
+ "resourceProvider": "Distributor",
229
+ "custodian": "DataCurator",
230
+ "owner": "RightsHolder",
231
+ "user": "Other",
232
+ "distributor": "Distributor",
233
+ "originator": "Producer",
234
+ "pointOfContact": "ContactPerson",
235
+ "principalInvestigator": "Supervisor",
236
+ "processor": "Other",
237
+ "publisher": "Distributor",
238
+ "author": "Researcher"
239
+ }
240
+
241
+ contnm = etree.SubElement(cont, util.nspath_eval('contributorName', NAMESPACES))
242
+ contnm.text = cnt.get('individualname',cnt.get('organization', ''))
243
+ cont.attrib['contributorType'] = roleMapping.get(cnt.get('role', ''),'Other')
244
+ if cnt.get('url').startswith('http'):
245
+ contid = etree.SubElement(cont, util.nspath_eval('nameIdentifier', NAMESPACES))
246
+ contid.attrib['nameIdentifierScheme'] = "URL"
247
+ contid.text = cnt['url']
248
+ if cnt['organization']:
249
+ contaf = etree.SubElement(cont, util.nspath_eval('affiliation', NAMESPACES))
250
+ contaf.text = cnt['organization']
251
+
252
+ if not hasPublisher and cnt.get('role', '').lower() in ['publisher','resourceProvider','distributor']:
253
+ hasPublisher = True
254
+ pb = etree.SubElement(node, util.nspath_eval('publisher', NAMESPACES))
255
+ pb.text = cnt.get('individualname',cnt.get('organization', ''))
256
+ elif cnt.get('role', '').lower() in ['originator','author','principalInvestigator']:
257
+ hasCreator = True
258
+ crea = etree.SubElement(creas, util.nspath_eval('creator', NAMESPACES))
259
+ creanm = etree.SubElement(crea, util.nspath_eval('creatorName', NAMESPACES))
260
+ creanm.text = cnt.get('individualname',cnt.get('organization', ''))
261
+ if cnt['url'] not in [None, '']:
262
+ creaid = etree.SubElement(crea, util.nspath_eval('nameIdentifier', NAMESPACES))
263
+ creaid.attrib['nameIdentifierScheme'] = "URL"
264
+ creaid.text = cnt['url']
265
+ if cnt['organization'] not in [None, '']:
266
+ creaff = etree.SubElement(crea, util.nspath_eval('affiliation', NAMESPACES))
267
+ creaff.text = cnt['organization']
268
+
269
+ except Exception as err:
270
+ LOGGER.exception(f"failed to parse contact of {cnt}: {err}")
271
+ except Exception as err:
272
+ LOGGER.exception(f"failed to parse contacts json of {cval}: {err}")
273
+ if not hasCreator:
274
+ crea = etree.SubElement(creas, util.nspath_eval('creator', NAMESPACES))
275
+ creanm = etree.SubElement(crea, util.nspath_eval('creatorName', NAMESPACES))
276
+ cval = util.getqattr(result, context.md_core_model['mappings']['pycsw:OrganizationName'])
277
+ creanm.text = cval
278
+
279
+ # <descriptions><description xml:lang="eng">foo</description></descriptions>
280
+ descriptions = etree.SubElement(node, util.nspath_eval('descriptions', NAMESPACES))
281
+ tval = util.getqattr(result, context.md_core_model['mappings']['pycsw:Abstract'])
282
+ description = etree.SubElement(descriptions, util.nspath_eval('description', NAMESPACES))
283
+ description.attrib[util.nspath_eval("xml:lang", NAMESPACES)]= util.getqattr(result, context.md_core_model['mappings']['pycsw:Language']) or "eng"
284
+ description.text = tval
285
+
286
+ # https://guidelines.openaire.eu/en/latest/data/field_language.html
287
+ # <language>eng</language>
288
+ tval = util.getqattr(result, context.md_core_model['mappings']['pycsw:Language'])
289
+ if tval not in [None, '']:
290
+ format = etree.SubElement(node, util.nspath_eval('Language', NAMESPACES))
291
+ format.text = tval
292
+
293
+ # https://guidelines.openaire.eu/en/latest/data/field_version.html?highlight=version
294
+ # <version>1.0</version>
295
+ tval = util.getqattr(result, context.md_core_model['mappings']['pycsw:Edition'])
296
+ if tval not in [None, '']:
297
+ format = etree.SubElement(node, util.nspath_eval('version', NAMESPACES))
298
+ format.text = tval
299
+
300
+ # https://guidelines.openaire.eu/en/latest/data/field_format.html
301
+ # <formats> <format>PDF</format> </formats>
302
+ tval = util.getqattr(result, context.md_core_model['mappings']['pycsw:Format'])
303
+ if tval not in [None, '']:
304
+ formats = etree.SubElement(node, util.nspath_eval('formats', NAMESPACES))
305
+ format = etree.SubElement(formats, util.nspath_eval('format', NAMESPACES))
306
+ format.text = tval
307
+
308
+ # <rightsList><rights rightsURI="https://example.com">example</rights></rightsList>
309
+ rights = etree.SubElement(node, util.nspath_eval('rightsList', NAMESPACES))
310
+ for r in ["AccessConstraints","OtherConstraints","Classification","ConditionApplyingToAccessAndUse"]:
311
+ rval = util.getqattr(result, context.md_core_model['mappings']['pycsw:'+r])
312
+ if rval not in [None, '']:
313
+ right = etree.SubElement(rights, util.nspath_eval('rights', NAMESPACES))
314
+ if rval.startswith('http'):
315
+ right.attrib['rightsURI'] = rval
316
+ right.text = r+':'+rval
317
+
318
+ # <sizes><size></size></sizes>
319
+
320
+ # "IsCitedBy","Cites","IsSupplementTo","IsSupplementedBy","IsContinuedBy","Continues","IsNewVersionOf","IsPreviousVersionOf","IsPartOf","HasPart","IsPublishedIn","IsReferencedBy","References","IsDocumentedBy","Documents","IsCompiledBy","Compiles","IsVariantFormOf","IsOriginalFormOf","IsIdenticalTo","HasMetadata","IsMetadataFor","Reviews","IsReviewedBy","IsDerivedFrom","IsSourceOf","Describes","IsDescribedBy","HasVersion","IsVersionOf","Requires","IsRequiredBy","Obsoletes","IsObsoletedBy"
321
+ # <relatedIdentifiers><relatedIdentifier relatedIdentifierType="URN" relationType="">doi:1234</relatedIdentifier></relatedIdentifiers>
322
+ # alternateIdentifiers/alternateIdentifier/@alternateIdentifierType
323
+
324
+ # Since Datacite is a metadata format related to the DOI to access a piece of content, the schema does not include a link to the actual file
325
+ # although internally Datacite uses a property `contentUrl`, suggestion to add links to content in the same way
326
+ rval = util.getqattr(result, context.md_core_model['mappings']['pycsw:Links'])
327
+ if rval not in [None, '', 'null']:
328
+ try:
329
+ for lnk in util.jsonify_links(rval):
330
+ try:
331
+ if lnk.get('url', '').startswith('http'):
332
+ ct = etree.SubElement(node, util.nspath_eval('contentUrl', NAMESPACES))
333
+ ct.text = lnk.get('url')
334
+ except Exception as err:
335
+ LOGGER.exception(f"failed to parse link of {rval}: {err}")
336
+ except Exception as err:
337
+ LOGGER.exception(f"failed to parse links json of {lnk}: {err}")
338
+
339
+ # <geoLocations><geoLocation><geoLocationBox><westBoundLongitude>41.090</...
340
+ bbox = util.getqattr(result, context.md_core_model['mappings']['pycsw:BoundingBox'])
341
+ if bbox not in [None, '']:
342
+ try:
343
+ bbox2 = util.wkt2geom(bbox)
344
+ except Exception as err:
345
+ LOGGER.debug(f'Geometry parsing error: {err}')
346
+ return None
347
+ bounds = etree.SubElement(node, util.nspath_eval('geoLocations', NAMESPACES))
348
+ bound = etree.SubElement(bounds, util.nspath_eval('geoLocation', NAMESPACES))
349
+ box = etree.SubElement(bound, util.nspath_eval('geoLocationBox', NAMESPACES))
350
+ wb = etree.SubElement(box, util.nspath_eval('westBoundLongitude', NAMESPACES))
351
+ wb.text = str(bbox2[0])
352
+ sb = etree.SubElement(box, util.nspath_eval('southBoundLatitude', NAMESPACES))
353
+ sb.text = str(bbox2[1])
354
+ eb = etree.SubElement(box, util.nspath_eval('eastBoundLongitude', NAMESPACES))
355
+ eb.text = str(bbox2[2])
356
+ nb = etree.SubElement(box, util.nspath_eval('northBoundLatitude', NAMESPACES))
357
+ nb.text = str(bbox2[3])
358
+
359
+ # Subtitle
360
+ sval = util.getqattr(result, context.md_core_model['mappings']['pycsw:AlternateTitle'])
361
+ if sval:
362
+ subtitle = etree.SubElement(titles, util.nspath_eval('title', NAMESPACES))
363
+ subtitle.attrib["titleType"] = "Subtitle"
364
+ subtitle.text = sval
365
+
366
+ # PublicationYear
367
+ dval = util.getqattr(result, context.md_core_model['mappings']['pycsw:PublicationDate'])
368
+ if dval in [None, '']:
369
+ dval = util.getqattr(result, context.md_core_model['mappings']['pycsw:Date'])
370
+ if dval not in [None, '']:
371
+ dt = datetime.fromisoformat(dval)
372
+ dt = dt.strftime("%Y")
373
+ etree.SubElement(node, util.nspath_eval('publicationYear', NAMESPACES)).text = dt
374
+
375
+ return node