bolognese 2.0.0 → 2.3.3
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +1 -1
- data/.github/workflows/release.yml +2 -2
- data/Gemfile.lock +13 -12
- data/bolognese.gemspec +4 -3
- data/lib/bolognese/author_utils.rb +4 -4
- data/lib/bolognese/datacite_utils.rb +1 -1
- data/lib/bolognese/metadata_utils.rb +2 -1
- data/lib/bolognese/readers/citeproc_reader.rb +6 -0
- data/lib/bolognese/readers/crossref_reader.rb +37 -3
- data/lib/bolognese/readers/datacite_reader.rb +1 -1
- data/lib/bolognese/readers/schema_org_reader.rb +26 -4
- data/lib/bolognese/utils.rb +14 -9
- data/lib/bolognese/version.rb +1 -1
- data/lib/bolognese/writers/datacite_json_writer.rb +1 -4
- data/lib/bolognese/writers/jats_writer.rb +4 -1
- data/lib/bolognese/writers/schema_org_writer.rb +5 -1
- data/resources/kernel-4/include/datacite-contributorType-v4.xsd +3 -1
- data/resources/kernel-4/include/datacite-dateType-v4.xsd +3 -1
- data/resources/kernel-4/include/datacite-relatedIdentifierType-v4.xsd +5 -2
- data/resources/kernel-4/include/datacite-relationType-v4.xsd +7 -3
- data/resources/kernel-4/include/datacite-resourceType-v4.xsd +5 -1
- data/resources/kernel-4/include/datacite-titleType-v4.xsd +1 -1
- data/resources/kernel-4/metadata.xsd +2 -1
- data/resources/kernel-4.6/include/datacite-contributorType-v4.xsd +37 -0
- data/resources/kernel-4.6/include/datacite-dateType-v4.xsd +27 -0
- data/resources/kernel-4.6/include/datacite-descriptionType-v4.xsd +19 -0
- data/resources/kernel-4.6/include/datacite-funderIdentifierType-v4.xsd +16 -0
- data/resources/kernel-4.6/include/datacite-nameType-v4.xsd +10 -0
- data/resources/kernel-4.6/include/datacite-numberType-v4.xsd +12 -0
- data/resources/kernel-4.6/include/datacite-relatedIdentifierType-v4.xsd +37 -0
- data/resources/kernel-4.6/include/datacite-relationType-v4.xsd +57 -0
- data/resources/kernel-4.6/include/datacite-resourceType-v4.xsd +49 -0
- data/resources/kernel-4.6/include/datacite-titleType-v4.xsd +14 -0
- data/resources/kernel-4.6/include/xml.xsd +286 -0
- data/resources/kernel-4.6/metadata.xsd +712 -0
- data/spec/author_utils_spec.rb +8 -2
- data/spec/datacite_utils_spec.rb +151 -1
- data/spec/fixtures/citeproc.json +6 -2
- data/spec/fixtures/crossref_schema_4.6_values.xml +183 -0
- data/spec/fixtures/datacite-example-ROR-nameIdentifiers.xml +8 -0
- data/spec/fixtures/datacite-example-full-v4.6.xml +114 -0
- data/spec/fixtures/datacite-xml-lang.xml +1 -1
- data/spec/fixtures/datacite_blank_name_identifier.xml +22 -0
- data/spec/fixtures/datacite_blank_publisher.xml +18 -0
- data/spec/fixtures/datacite_journal_article.xml +64 -0
- data/spec/fixtures/schema_org.json +1 -0
- data/spec/fixtures/schema_org_4.6_attributes.json +108 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/insert_contributors_Translator/supports_Translator_contributorType.yml +71 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/insert_dates_with_Coverage/inserts_date_with_dateType_Coverage.yml +71 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/insert_related_identifiers_CSTR/supports_CSTR_relatedIdentifierType.yml +71 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/insert_related_identifiers_HasTranslation/supports_HasTranslation_relationType.yml +71 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/insert_related_identifiers_RRID/supports_RRID_relatedIdentifierType.yml +71 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/insert_resource_type_with_Award/supports_Award_as_resourceTypeGeneral.yml +71 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/insert_resource_type_with_Project/supports_Project_as_resourceTypeGeneral.yml +71 -0
- data/spec/readers/citeproc_reader_spec.rb +1 -0
- data/spec/readers/crossref_reader_spec.rb +31 -0
- data/spec/readers/datacite_reader_spec.rb +91 -0
- data/spec/readers/schema_org_reader_spec.rb +28 -1
- data/spec/writers/citation_writer_spec.rb +9 -0
- data/spec/writers/citeproc_writer_spec.rb +9 -0
- data/spec/writers/datacite_json_writer_spec.rb +16 -32
- data/spec/writers/datacite_writer_spec.rb +71 -0
- data/spec/writers/jats_writer_spec.rb +8 -1
- data/spec/writers/schema_org_writer_spec.rb +49 -0
- metadata +58 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1a86efd4d59883de399bfae917077f97c5f5e33bd698bc70fc4a3daa40736acc
|
|
4
|
+
data.tar.gz: da3ac310e177b6ad9733ff56cb9893cfe107c0beb930167b7b8f392dfb2332f4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee269b568dd16e08da5c10f00155a3e0b55e9725c1d6aa114c6c3a5020dfe05c2df89388a9bc394a6274e86ca81567f4f756dd31bcaf5faa12dff2a7df275308
|
|
7
|
+
data.tar.gz: 26245d3b2e4553616ba0708047b542f4092240e4cc251ae578de502010ba69a3d6700a5df48f59cd427b7f0eaf498a15cc043cd78ad799572bd589dfcbad6784
|
data/.github/workflows/ci.yml
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
bolognese (2.
|
|
4
|
+
bolognese (2.3.3)
|
|
5
5
|
activesupport (>= 4.2.5)
|
|
6
6
|
benchmark_methods (~> 0.7)
|
|
7
7
|
bibtex-ruby (>= 5.1.0)
|
|
@@ -16,9 +16,9 @@ PATH
|
|
|
16
16
|
json-ld-preloaded (~> 3.1, >= 3.1.3)
|
|
17
17
|
jsonlint (~> 0.3.0)
|
|
18
18
|
loofah (~> 2.0, >= 2.0.3)
|
|
19
|
-
maremma (
|
|
19
|
+
maremma (~> 5.0)
|
|
20
20
|
namae (~> 1.0)
|
|
21
|
-
nokogiri (
|
|
21
|
+
nokogiri (~> 1.16, >= 1.16.2)
|
|
22
22
|
oj (~> 3.10)
|
|
23
23
|
oj_mimic_json (~> 1.0, >= 1.0.1)
|
|
24
24
|
postrank-uri (~> 1.0, >= 1.0.18)
|
|
@@ -95,10 +95,10 @@ GEM
|
|
|
95
95
|
concurrent-ruby (~> 1.0)
|
|
96
96
|
iso8601 (0.9.1)
|
|
97
97
|
json (2.6.2)
|
|
98
|
-
json-canonicalization (0.3.
|
|
99
|
-
json-ld (3.2.
|
|
98
|
+
json-canonicalization (0.3.1)
|
|
99
|
+
json-ld (3.2.4)
|
|
100
100
|
htmlentities (~> 4.3)
|
|
101
|
-
json-canonicalization (~> 0.3
|
|
101
|
+
json-canonicalization (~> 0.3)
|
|
102
102
|
link_header (~> 0.0, >= 0.0.8)
|
|
103
103
|
multi_json (~> 1.15)
|
|
104
104
|
rack (>= 2.2, < 4)
|
|
@@ -114,7 +114,7 @@ GEM
|
|
|
114
114
|
loofah (2.21.3)
|
|
115
115
|
crass (~> 1.0.2)
|
|
116
116
|
nokogiri (>= 1.12.0)
|
|
117
|
-
maremma (
|
|
117
|
+
maremma (5.0.0)
|
|
118
118
|
activesupport (>= 4.2.5)
|
|
119
119
|
addressable (>= 2.3.6)
|
|
120
120
|
builder (~> 3.2, >= 3.2.2)
|
|
@@ -125,17 +125,17 @@ GEM
|
|
|
125
125
|
faraday-follow_redirects (~> 0.3.0)
|
|
126
126
|
faraday-gzip (~> 0.1.0)
|
|
127
127
|
faraday-multipart (~> 1.0.4)
|
|
128
|
-
nokogiri (
|
|
128
|
+
nokogiri (~> 1.16, >= 1.16.2)
|
|
129
129
|
oj (>= 2.8.3)
|
|
130
130
|
oj_mimic_json (~> 1.0, >= 1.0.1)
|
|
131
131
|
matrix (0.4.2)
|
|
132
|
-
mini_portile2 (2.8.
|
|
132
|
+
mini_portile2 (2.8.5)
|
|
133
133
|
minitest (5.18.0)
|
|
134
134
|
multi_json (1.15.0)
|
|
135
135
|
multipart-post (2.3.0)
|
|
136
136
|
namae (1.1.1)
|
|
137
|
-
nokogiri (1.
|
|
138
|
-
mini_portile2 (~> 2.8.
|
|
137
|
+
nokogiri (1.16.2)
|
|
138
|
+
mini_portile2 (~> 2.8.2)
|
|
139
139
|
racc (~> 1.4)
|
|
140
140
|
oj (3.14.2)
|
|
141
141
|
oj_mimic_json (1.0.1)
|
|
@@ -225,6 +225,7 @@ DEPENDENCIES
|
|
|
225
225
|
bundler (>= 1.0)
|
|
226
226
|
byebug
|
|
227
227
|
hashdiff (>= 1.0.0.beta1, < 2.0.0)
|
|
228
|
+
json-canonicalization (= 0.3.1)
|
|
228
229
|
rack-test (~> 0)
|
|
229
230
|
rake (~> 12.0)
|
|
230
231
|
rspec (~> 3.4)
|
|
@@ -234,4 +235,4 @@ DEPENDENCIES
|
|
|
234
235
|
webmock (~> 3.0, >= 3.0.1)
|
|
235
236
|
|
|
236
237
|
BUNDLED WITH
|
|
237
|
-
2.
|
|
238
|
+
2.5.5
|
data/bolognese.gemspec
CHANGED
|
@@ -13,12 +13,12 @@ Gem::Specification.new do |s|
|
|
|
13
13
|
s.version = Bolognese::VERSION
|
|
14
14
|
s.extra_rdoc_files = ["README.md"]
|
|
15
15
|
s.license = 'MIT'
|
|
16
|
-
s.required_ruby_version = ['>=
|
|
16
|
+
s.required_ruby_version = ['>=3.0']
|
|
17
17
|
|
|
18
18
|
# Declare dependencies here, rather than in the Gemfile
|
|
19
|
-
s.add_dependency 'maremma', '
|
|
19
|
+
s.add_dependency 'maremma', '~> 5.0'
|
|
20
20
|
#s.add_dependency 'faraday', '~> 0.17.3'
|
|
21
|
-
s.add_dependency 'nokogiri', '
|
|
21
|
+
s.add_dependency 'nokogiri', '~> 1.16', '>= 1.16.2'
|
|
22
22
|
s.add_dependency 'loofah', '~> 2.0', '>= 2.0.3'
|
|
23
23
|
s.add_dependency 'builder', '~> 3.2', '>= 3.2.2'
|
|
24
24
|
s.add_dependency 'activesupport', '>= 4.2.5'
|
|
@@ -50,6 +50,7 @@ Gem::Specification.new do |s|
|
|
|
50
50
|
s.add_development_dependency 'simplecov', '0.17.1'
|
|
51
51
|
s.add_development_dependency 'hashdiff', ['>= 1.0.0.beta1', '< 2.0.0']
|
|
52
52
|
s.add_development_dependency 'byebug'
|
|
53
|
+
s.add_development_dependency 'json-canonicalization', '0.3.1'
|
|
53
54
|
|
|
54
55
|
s.require_paths = ["lib"]
|
|
55
56
|
s.files = `git ls-files`.split($/)
|
|
@@ -30,20 +30,20 @@ module Bolognese
|
|
|
30
30
|
name_type = parse_attributes(author.fetch("creatorName", nil), content: "nameType", first: true) || parse_attributes(author.fetch("contributorName", nil), content: "nameType", first: true)
|
|
31
31
|
|
|
32
32
|
name_identifiers = Array.wrap(author.fetch("nameIdentifier", nil)).map do |ni|
|
|
33
|
-
ni["__content__"]
|
|
33
|
+
name_identifier = ni["__content__"].strip if ni["__content__"].present?
|
|
34
34
|
if ni["nameIdentifierScheme"] == "ORCID"
|
|
35
35
|
{
|
|
36
|
-
"nameIdentifier" => normalize_orcid(
|
|
36
|
+
"nameIdentifier" => normalize_orcid(name_identifier),
|
|
37
37
|
"schemeUri" => "https://orcid.org",
|
|
38
38
|
"nameIdentifierScheme" => "ORCID" }.compact
|
|
39
39
|
elsif ni["nameIdentifierScheme"] == "ROR"
|
|
40
40
|
{
|
|
41
|
-
"nameIdentifier" => normalize_ror(
|
|
41
|
+
"nameIdentifier" => normalize_ror(name_identifier),
|
|
42
42
|
"schemeUri" => "https://ror.org",
|
|
43
43
|
"nameIdentifierScheme" => "ROR" }.compact
|
|
44
44
|
else
|
|
45
45
|
{
|
|
46
|
-
"nameIdentifier" =>
|
|
46
|
+
"nameIdentifier" => name_identifier,
|
|
47
47
|
"schemeUri" => ni.fetch("schemeURI", nil),
|
|
48
48
|
"nameIdentifierScheme" => ni["nameIdentifierScheme"] }.compact
|
|
49
49
|
end
|
|
@@ -128,7 +128,7 @@ module Bolognese
|
|
|
128
128
|
def insert_resource_type(xml)
|
|
129
129
|
return xml unless types.is_a?(Hash) && (types["schemaOrg"].present? || types["resourceTypeGeneral"])
|
|
130
130
|
|
|
131
|
-
xml.resourceType(types["resourceType"]
|
|
131
|
+
xml.resourceType(types["resourceType"],
|
|
132
132
|
'resourceTypeGeneral' => types["resourceTypeGeneral"] || Metadata::SO_TO_DC_TRANSLATIONS[types["schemaOrg"]] || "Other")
|
|
133
133
|
end
|
|
134
134
|
|
|
@@ -96,7 +96,7 @@ module Bolognese
|
|
|
96
96
|
if container.present?
|
|
97
97
|
container["title"]
|
|
98
98
|
elsif types["citeproc"] == "article-journal"
|
|
99
|
-
publisher
|
|
99
|
+
publisher["name"] if publisher.present?
|
|
100
100
|
else
|
|
101
101
|
nil
|
|
102
102
|
end
|
|
@@ -153,6 +153,7 @@ module Bolognese
|
|
|
153
153
|
"language" => language,
|
|
154
154
|
"author" => author,
|
|
155
155
|
"contributor" => to_citeproc(contributors),
|
|
156
|
+
"translator" => contributors ? to_citeproc(contributors.select { |c| c["contributorType"] == "Translator" }) : nil,
|
|
156
157
|
"issued" => get_date(dates, "Issued") ? get_date_parts(get_date(dates, "Issued")) : get_date_parts(publication_year.to_s),
|
|
157
158
|
"submitted" => Array.wrap(dates).find { |d| d["dateType"] == "Submitted" }.to_h.fetch("__content__", nil),
|
|
158
159
|
"abstract" => parse_attributes(descriptions, content: "description", first: true),
|
|
@@ -52,6 +52,12 @@ module Bolognese
|
|
|
52
52
|
[{ "nameType" => "Organizational", "name" => ":(unav)" }]
|
|
53
53
|
end
|
|
54
54
|
contributors = get_authors(from_citeproc(Array.wrap(meta.fetch("editor", nil))))
|
|
55
|
+
translators = get_authors(from_citeproc(Array.wrap(meta.fetch("translator", nil))))
|
|
56
|
+
translators.each do |translator|
|
|
57
|
+
translator["contributorType"] = "Translator"
|
|
58
|
+
end
|
|
59
|
+
contributors += translators
|
|
60
|
+
|
|
55
61
|
dates = if date = get_date_from_date_parts(meta.fetch("issued", nil))
|
|
56
62
|
if Date.edtf(date).present?
|
|
57
63
|
[{ "date" => date,
|
|
@@ -4,6 +4,12 @@ module Bolognese
|
|
|
4
4
|
module Readers
|
|
5
5
|
module CrossrefReader
|
|
6
6
|
# CrossRef types from https://api.crossref.org/types
|
|
7
|
+
|
|
8
|
+
CR_TO_DC_CONTRIBUTOR_TYPES = {
|
|
9
|
+
"editor" => "Editor",
|
|
10
|
+
"translator" => "Translator",
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
def get_crossref(id: nil, **options)
|
|
8
14
|
return { "string" => nil, "state" => "not_found" } unless id.present?
|
|
9
15
|
|
|
@@ -138,7 +144,7 @@ module Bolognese
|
|
|
138
144
|
|
|
139
145
|
state = meta.present? || read_options.present? ? "findable" : "not_found"
|
|
140
146
|
|
|
141
|
-
related_identifiers = Array.wrap(crossref_is_part_of(journal_metadata)) + Array.wrap(crossref_references(bibliographic_metadata))
|
|
147
|
+
related_identifiers = Array.wrap(crossref_is_part_of(journal_metadata)) + Array.wrap(crossref_references(bibliographic_metadata)) + Array.wrap(crossref_has_translation(program_metadata)) + Array.wrap(crossref_is_translation_of(program_metadata))
|
|
142
148
|
|
|
143
149
|
container = if journal_metadata.present?
|
|
144
150
|
issn = normalize_issn(journal_metadata.to_h.fetch("issn", nil))
|
|
@@ -187,7 +193,7 @@ module Bolognese
|
|
|
187
193
|
"titles" => titles,
|
|
188
194
|
"identifiers" => identifiers,
|
|
189
195
|
"creators" => crossref_people(bibliographic_metadata, "author"),
|
|
190
|
-
"contributors" => crossref_people(bibliographic_metadata, "editor"),
|
|
196
|
+
"contributors" => crossref_people(bibliographic_metadata, "editor") + crossref_people(bibliographic_metadata, "translator"),
|
|
191
197
|
"funding_references" => crossref_funding_reference(program_metadata),
|
|
192
198
|
"publisher" => publisher,
|
|
193
199
|
"container" => container,
|
|
@@ -276,13 +282,15 @@ module Bolognese
|
|
|
276
282
|
end
|
|
277
283
|
end.compact
|
|
278
284
|
|
|
285
|
+
contributor_type = CR_TO_DC_CONTRIBUTOR_TYPES[a["contributor_role"]]
|
|
286
|
+
|
|
279
287
|
{ "nameType" => "Personal",
|
|
280
288
|
"nameIdentifiers" => name_identifiers,
|
|
281
289
|
"name" => [family_name, given_name].compact.join(", "),
|
|
282
290
|
"givenName" => given_name,
|
|
283
291
|
"familyName" => family_name,
|
|
284
292
|
"affiliation" => affiliation.presence,
|
|
285
|
-
"contributorType" =>
|
|
293
|
+
"contributorType" => contributor_type }.compact
|
|
286
294
|
else
|
|
287
295
|
{ "nameType" => "Organizational",
|
|
288
296
|
"name" => a["name"] || a["__content__"] }
|
|
@@ -362,6 +370,32 @@ module Bolognese
|
|
|
362
370
|
end
|
|
363
371
|
end.compact.unwrap
|
|
364
372
|
end
|
|
373
|
+
|
|
374
|
+
def crossref_has_translation(program_metadata)
|
|
375
|
+
refs = program_metadata.dig("related_item") if program_metadata.is_a?(Hash)
|
|
376
|
+
Array.wrap(refs).select { |a| a.dig("intra_work_relation", "relationship_type") == "hasTranslation" }.map do |c|
|
|
377
|
+
if c.dig("intra_work_relation", "identifier_type") == "doi"
|
|
378
|
+
{ "relatedIdentifier" => parse_attributes(c["intra_work_relation"]).downcase,
|
|
379
|
+
"relationType" => "HasTranslation",
|
|
380
|
+
"relatedIdentifierType" => "DOI" }.compact
|
|
381
|
+
else
|
|
382
|
+
nil
|
|
383
|
+
end
|
|
384
|
+
end.compact.unwrap
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def crossref_is_translation_of(program_metadata)
|
|
388
|
+
refs = program_metadata.dig("related_item") if program_metadata.is_a?(Hash)
|
|
389
|
+
Array.wrap(refs).select { |a| a.dig("intra_work_relation", "relationship_type") == "isTranslationOf" }.map do |c|
|
|
390
|
+
if c.dig("intra_work_relation", "identifier_type") == "doi"
|
|
391
|
+
{ "relatedIdentifier" => parse_attributes(c["intra_work_relation"]).downcase,
|
|
392
|
+
"relationType" => "IsTranslationOf",
|
|
393
|
+
"relatedIdentifierType" => "DOI" }.compact
|
|
394
|
+
else
|
|
395
|
+
nil
|
|
396
|
+
end
|
|
397
|
+
end.compact.unwrap
|
|
398
|
+
end
|
|
365
399
|
end
|
|
366
400
|
end
|
|
367
401
|
end
|
|
@@ -101,7 +101,7 @@ module Bolognese
|
|
|
101
101
|
{ "name" => r.strip }
|
|
102
102
|
elsif r.is_a?(Hash)
|
|
103
103
|
{
|
|
104
|
-
"name" => r["__content__"].strip,
|
|
104
|
+
"name" => r["__content__"].present? ? r["__content__"].strip : nil,
|
|
105
105
|
"publisherIdentifier" => r["publisherIdentifierScheme"] == "ROR" ? normalize_ror(r["publisherIdentifier"]) : r["publisherIdentifier"],
|
|
106
106
|
"publisherIdentifierScheme" => r["publisherIdentifierScheme"],
|
|
107
107
|
"schemeUri" => r["schemeURI"],
|
|
@@ -10,7 +10,9 @@ module Bolognese
|
|
|
10
10
|
"isPartOf" => "IsPartOf",
|
|
11
11
|
"hasPart" => "HasPart",
|
|
12
12
|
"isPredecessor" => "IsPreviousVersionOf",
|
|
13
|
-
"isSuccessor" => "IsNewVersionOf"
|
|
13
|
+
"isSuccessor" => "IsNewVersionOf",
|
|
14
|
+
"workTranslation" => "HasTranslation",
|
|
15
|
+
"translationOfWork" => "IsTranslationOf"
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
SO_TO_DC_REVERSE_RELATION_TYPES = {
|
|
@@ -74,8 +76,17 @@ module Bolognese
|
|
|
74
76
|
creators = get_authors(from_schema_org_creators(Array.wrap(authors)))
|
|
75
77
|
end
|
|
76
78
|
contributors = get_authors(from_schema_org_contributors(Array.wrap(meta.fetch("editor", nil))))
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
translators = get_authors(from_schema_org_contributors(Array.wrap(meta.fetch("translator", nil))))
|
|
80
|
+
translators.map! do |translator|
|
|
81
|
+
translator["contributorType"] = "Translator"
|
|
82
|
+
translator
|
|
83
|
+
end
|
|
84
|
+
contributors += translators
|
|
85
|
+
|
|
86
|
+
publisher = {
|
|
87
|
+
"name" => parse_attributes(meta.fetch("publisher", nil), content: "name", first: true),
|
|
88
|
+
"publisherIdentifier" => parse_attributes(meta.fetch("publisher", nil), content: "@id", first: true),
|
|
89
|
+
}.compact if meta.fetch("publisher", nil).present?
|
|
79
90
|
|
|
80
91
|
ct = (schema_org == "Dataset") ? "includedInDataCatalog" : "Periodical"
|
|
81
92
|
container = if meta.fetch(ct, nil).present?
|
|
@@ -103,7 +114,9 @@ module Bolognese
|
|
|
103
114
|
Array.wrap(schema_org_references(meta)) +
|
|
104
115
|
Array.wrap(schema_org_is_referenced_by(meta)) +
|
|
105
116
|
Array.wrap(schema_org_is_supplement_to(meta)) +
|
|
106
|
-
Array.wrap(schema_org_is_supplemented_by(meta))
|
|
117
|
+
Array.wrap(schema_org_is_supplemented_by(meta)) +
|
|
118
|
+
Array.wrap(schema_org_has_translation(meta)) +
|
|
119
|
+
Array.wrap(schema_org_is_translation_of(meta))
|
|
107
120
|
|
|
108
121
|
rights_list = Array.wrap(meta.fetch("license", nil)).compact.map do |rl|
|
|
109
122
|
hsh_to_spdx("__content__" => rl["name"], "rightsURI" => rl["id"])
|
|
@@ -124,6 +137,7 @@ module Bolognese
|
|
|
124
137
|
dates << { "date" => meta.fetch("datePublished"), "dateType" => "Issued" } if Date.edtf(meta.fetch("datePublished", nil)).present?
|
|
125
138
|
dates << { "date" => meta.fetch("dateCreated"), "dateType" => "Created" } if Date.edtf(meta.fetch("dateCreated", nil)).present?
|
|
126
139
|
dates << { "date" => meta.fetch("dateModified"), "dateType" => "Updated" } if Date.edtf(meta.fetch("dateModified", nil)).present?
|
|
140
|
+
dates << { "date" => meta.fetch("temporalCoverage"), "dateType" => "Coverage" } if Date.edtf(meta.fetch("temporalCoverage", nil)).present?
|
|
127
141
|
publication_year = meta.fetch("datePublished")[0..3] if meta.fetch("datePublished", nil).present?
|
|
128
142
|
|
|
129
143
|
if meta.fetch("inLanguage", nil).is_a?(String)
|
|
@@ -237,6 +251,14 @@ module Bolognese
|
|
|
237
251
|
schema_org_related_identifier(meta, relation_type: "isBasedOn")
|
|
238
252
|
end
|
|
239
253
|
|
|
254
|
+
def schema_org_has_translation(meta)
|
|
255
|
+
schema_org_related_identifier(meta, relation_type: "workTranslation", )
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def schema_org_is_translation_of(meta)
|
|
259
|
+
schema_org_related_identifier(meta, relation_type: "translationOfWork")
|
|
260
|
+
end
|
|
261
|
+
|
|
240
262
|
end
|
|
241
263
|
end
|
|
242
264
|
end
|
data/lib/bolognese/utils.rb
CHANGED
|
@@ -78,7 +78,9 @@ module Bolognese
|
|
|
78
78
|
"Other" => "CreativeWork",
|
|
79
79
|
# not part of DataCite schema, but used internally
|
|
80
80
|
"Periodical" => "Periodical",
|
|
81
|
-
"DataCatalog" => "DataCatalog"
|
|
81
|
+
"DataCatalog" => "DataCatalog",
|
|
82
|
+
"Award" => "Grant",
|
|
83
|
+
"Project" => "Project"
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
DC_TO_CP_TRANSLATIONS = {
|
|
@@ -600,12 +602,12 @@ module Bolognese
|
|
|
600
602
|
end
|
|
601
603
|
|
|
602
604
|
def validate_orcid(orcid)
|
|
603
|
-
orcid = Array(/\A(?:(?:http|https):\/\/(?:(?:www|sandbox)?\.)?orcid\.org\/)?(\d{4}[[:space:]-]\d{4}[[:space:]-]\d{4}[[:space:]-]\d{3}[0-9X]+)\z/.match(orcid)).last
|
|
605
|
+
orcid = Array(/\A(?:(?:http|https):\/\/(?:(?:www|sandbox)?\.)?orcid\.org\/)?(\d{4}[[:space:]-]\d{4}[[:space:]-]\d{4}[[:space:]-]\d{3}[0-9X]+)\/{0,1}\z/.match(orcid)).last
|
|
604
606
|
orcid.gsub(/[[:space:]]/, "-") if orcid.present?
|
|
605
607
|
end
|
|
606
608
|
|
|
607
609
|
def validate_ror(ror)
|
|
608
|
-
Array(/^(?:(?:(?:http|https):\/\/)?ror\.org\/)?(0\w{6}\d{2})$/.match(ror)).last
|
|
610
|
+
Array(/^(?:(?:(?:http|https):\/\/)?ror\.org\/)?(0\w{6}\d{2})\/{0,1}$/.match(ror)).last
|
|
609
611
|
end
|
|
610
612
|
|
|
611
613
|
def validate_orcid_scheme(orcid_scheme)
|
|
@@ -825,7 +827,8 @@ module Bolognese
|
|
|
825
827
|
|
|
826
828
|
def to_schema_org_contributors(element)
|
|
827
829
|
element = Array.wrap(element).map do |c|
|
|
828
|
-
|
|
830
|
+
transformed_c = c.dup
|
|
831
|
+
transformed_c["affiliation"] = Array.wrap(c["affiliation"]).map do |a|
|
|
829
832
|
if a.is_a?(String)
|
|
830
833
|
name = a
|
|
831
834
|
affiliation_identifier = nil
|
|
@@ -839,10 +842,10 @@ module Bolognese
|
|
|
839
842
|
"@id" => affiliation_identifier,
|
|
840
843
|
"name" => name }.compact
|
|
841
844
|
end.unwrap
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
845
|
+
transformed_c["@type"] = c["nameType"].present? ? c["nameType"][0..-3] : nil
|
|
846
|
+
transformed_c["@id"] = Array.wrap(c["nameIdentifiers"]).first.to_h.fetch("nameIdentifier", nil)
|
|
847
|
+
transformed_c["name"] = c["familyName"].present? ? [c["givenName"], c["familyName"]].join(" ") : c["name"]
|
|
848
|
+
transformed_c.except("nameIdentifiers", "nameType").compact
|
|
846
849
|
end.unwrap
|
|
847
850
|
end
|
|
848
851
|
|
|
@@ -1234,7 +1237,9 @@ module Bolognese
|
|
|
1234
1237
|
"urn" => "URN",
|
|
1235
1238
|
"md5" => "md5",
|
|
1236
1239
|
"minid" => "minid",
|
|
1237
|
-
"dataguid" => "dataguid"
|
|
1240
|
+
"dataguid" => "dataguid",
|
|
1241
|
+
"cstr" => "CSTR",
|
|
1242
|
+
"rrid" => "RRID"
|
|
1238
1243
|
}
|
|
1239
1244
|
|
|
1240
1245
|
identifierTypes[identifier_type.downcase] || identifier_type
|
data/lib/bolognese/version.rb
CHANGED
|
@@ -4,11 +4,8 @@ module Bolognese
|
|
|
4
4
|
module Writers
|
|
5
5
|
module DataciteJsonWriter
|
|
6
6
|
def datacite_json
|
|
7
|
-
# Remove the following change for the schema 4.5 release
|
|
8
7
|
if crosscite_hsh.present?
|
|
9
|
-
|
|
10
|
-
datacite_json_hsh['publisher'] = self.publisher['name'] if self.publisher&.respond_to?(:to_hash) && self.publisher.has_key?('name') && !self.publisher['name'].blank?
|
|
11
|
-
JSON.pretty_generate datacite_json_hsh.transform_keys! { |key| key.camelcase(uppercase_first_letter = :lower) }
|
|
8
|
+
JSON.pretty_generate crosscite_hsh.transform_keys! { |key| key.camelcase(uppercase_first_letter = :lower) }
|
|
12
9
|
end
|
|
13
10
|
end
|
|
14
11
|
end
|
|
@@ -86,7 +86,10 @@ module Bolognese
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
def insert_publisher_name(xml)
|
|
89
|
-
|
|
89
|
+
attributes = {
|
|
90
|
+
"xml:lang" => publisher["lang"]
|
|
91
|
+
}.compact
|
|
92
|
+
xml.send("publisher-name", attributes, publisher["name"])
|
|
90
93
|
end
|
|
91
94
|
|
|
92
95
|
def insert_publication_date(xml)
|
|
@@ -13,6 +13,7 @@ module Bolognese
|
|
|
13
13
|
"name" => parse_attributes(titles, content: "title", first: true),
|
|
14
14
|
"author" => to_schema_org_creators(creators),
|
|
15
15
|
"editor" => to_schema_org_contributors(contributors),
|
|
16
|
+
"translator" => contributors ? to_schema_org_contributors(contributors.select { |c| c["contributorType"] == "Translator" }) : nil,
|
|
16
17
|
"description" => parse_attributes(abstract_description, content: "description", first: true),
|
|
17
18
|
"license" => Array.wrap(rights_list).map { |l| l["rightsUri"] }.compact.unwrap,
|
|
18
19
|
"version" => version_info,
|
|
@@ -23,6 +24,7 @@ module Bolognese
|
|
|
23
24
|
"dateCreated" => get_date(dates, "Created"),
|
|
24
25
|
"datePublished" => get_date(dates, "Issued") || publication_year,
|
|
25
26
|
"dateModified" => get_date(dates, "Updated"),
|
|
27
|
+
"temporalCoverage" => get_date(dates, "Coverage"),
|
|
26
28
|
"pageStart" => container.to_h["firstPage"],
|
|
27
29
|
"pageEnd" => container.to_h["lastPage"],
|
|
28
30
|
"spatialCoverage" => to_schema_org_spatial_coverage(geo_locations),
|
|
@@ -32,12 +34,14 @@ module Bolognese
|
|
|
32
34
|
"predecessor_of" => to_schema_org_relation(related_identifiers: related_identifiers, relation_type: "IsPreviousVersionOf"),
|
|
33
35
|
"successor_of" => to_schema_org_relation(related_identifiers: related_identifiers, relation_type: "IsNewVersionOf"),
|
|
34
36
|
"citation" => to_schema_org_relation(related_identifiers: related_identifiers, relation_type: "References"),
|
|
37
|
+
"workTranslation" => to_schema_org_relation(related_identifiers: related_identifiers, relation_type: "HasTranslation"),
|
|
38
|
+
"translationOfWork" => to_schema_org_relation(related_identifiers: related_identifiers, relation_type: "IsTranslationOf"),
|
|
35
39
|
"@reverse" => reverse.presence,
|
|
36
40
|
"contentUrl" => Array.wrap(content_url).unwrap,
|
|
37
41
|
"schemaVersion" => schema_version,
|
|
38
42
|
"periodical" => types.present? ? ((types["schemaOrg"] != "Dataset") && container.present? ? to_schema_org(container) : nil) : nil,
|
|
39
43
|
"includedInDataCatalog" => types.present? ? ((types["schemaOrg"] == "Dataset") && container.present? ? to_schema_org_container(container, type: "Dataset") : nil) : nil,
|
|
40
|
-
"publisher" => publisher.present? ? { "@type" => "Organization", "name" => publisher["name"] } : nil,
|
|
44
|
+
"publisher" => publisher.present? ? { "@type" => "Organization", "@id" => publisher["publisherIdentifier"], "name" => publisher["name"] }.compact : nil,
|
|
41
45
|
"funder" => to_schema_org_funder(funding_references),
|
|
42
46
|
"provider" => agency.present? ? { "@type" => "Organization", "name" => agency } : nil
|
|
43
47
|
}.compact.presence
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
<!-- Version 1.0 - Created 2011-01-13 - FZ, TIB, Germany
|
|
3
3
|
2013-05 v3.0: Addition of ID to simpleType element, added values "ResearchGroup" & "Other"
|
|
4
4
|
2014-08-20 v3.1: Addition of value "DataCurator"
|
|
5
|
-
2015-05-14 v4.0 dropped value "Funder", use new "funderReference"
|
|
5
|
+
2015-05-14 v4.0 dropped value "Funder", use new "funderReference"
|
|
6
|
+
2024-12-31 v4.6: Addition of value "Translator" -->
|
|
6
7
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://datacite.org/schema/kernel-4" targetNamespace="http://datacite.org/schema/kernel-4" elementFormDefault="qualified">
|
|
7
8
|
<xs:simpleType name="contributorType" id="contributorType">
|
|
8
9
|
<xs:annotation>
|
|
@@ -29,6 +30,7 @@
|
|
|
29
30
|
<xs:enumeration value="Researcher" />
|
|
30
31
|
<xs:enumeration value="Sponsor" />
|
|
31
32
|
<xs:enumeration value="Supervisor" />
|
|
33
|
+
<xs:enumeration value="Translator" />
|
|
32
34
|
<xs:enumeration value="WorkPackageLeader" />
|
|
33
35
|
</xs:restriction>
|
|
34
36
|
</xs:simpleType>
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
<!-- Version 1.0 - Created 2011-01-13 - FZ, TIB, Germany
|
|
3
3
|
2013-05 v3.0: Addition of ID to simpleType element; addition of value "Collected"; deleted "StartDate" & "EndDate"
|
|
4
4
|
2017-10-23 v4.1: Addition of value "Other"
|
|
5
|
-
2019-02-14 v4.2: Addition of value "Withdrawn"
|
|
5
|
+
2019-02-14 v4.2: Addition of value "Withdrawn"
|
|
6
|
+
2024-12-31 v4.6: Addition of value "Coverage"-->
|
|
6
7
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://datacite.org/schema/kernel-4" targetNamespace="http://datacite.org/schema/kernel-4" elementFormDefault="qualified">
|
|
7
8
|
<xs:simpleType name="dateType" id="dateType">
|
|
8
9
|
<xs:annotation>
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
<xs:enumeration value="Available" />
|
|
14
15
|
<xs:enumeration value="Collected" />
|
|
15
16
|
<xs:enumeration value="Copyrighted" />
|
|
17
|
+
<xs:enumeration value="Coverage" />
|
|
16
18
|
<xs:enumeration value="Created" />
|
|
17
19
|
<xs:enumeration value="Issued" />
|
|
18
20
|
<xs:enumeration value="Other" />
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
<!-- Version 1.0 - Created 2011-01-13 - FZ, TIB, Germany
|
|
3
3
|
2013-05 v3.0: Addition of ID to simpleType element; addition of value "PMID"
|
|
4
4
|
2014-08-20 v3.1: Addition of values "arxiv" and "bibcode"
|
|
5
|
-
2015-02-12 v4.0 Addition of value "IGSN"
|
|
6
|
-
2019-02-14 v4.2 Addition of value "w3id"
|
|
5
|
+
2015-02-12 v4.0: Addition of value "IGSN"
|
|
6
|
+
2019-02-14 v4.2: Addition of value "w3id"
|
|
7
|
+
2024-12-31 v4.5: Addition of values "CSTR", "RRID" -->
|
|
7
8
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://datacite.org/schema/kernel-4" targetNamespace="http://datacite.org/schema/kernel-4" elementFormDefault="qualified">
|
|
8
9
|
<xs:simpleType name="relatedIdentifierType" id="relatedIdentifierType">
|
|
9
10
|
<xs:annotation>
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
<xs:enumeration value="ARK" />
|
|
14
15
|
<xs:enumeration value="arXiv" />
|
|
15
16
|
<xs:enumeration value="bibcode" />
|
|
17
|
+
<xs:enumeration value="CSTR" />
|
|
16
18
|
<xs:enumeration value="DOI" />
|
|
17
19
|
<xs:enumeration value="EAN13" />
|
|
18
20
|
<xs:enumeration value="EISSN" />
|
|
@@ -25,6 +27,7 @@
|
|
|
25
27
|
<xs:enumeration value="LSID" />
|
|
26
28
|
<xs:enumeration value="PMID" />
|
|
27
29
|
<xs:enumeration value="PURL" />
|
|
30
|
+
<xs:enumeration value="RRID" />
|
|
28
31
|
<xs:enumeration value="UPC" />
|
|
29
32
|
<xs:enumeration value="URL" />
|
|
30
33
|
<xs:enumeration value="URN" />
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
2011-01-13 v1.0 - FZ, TIB, Germany
|
|
4
4
|
2013-05 v3.0: Addition of ID to simpleType element, addition of values "IsIdenticalTo", "HasMetadata" & "IsMetadataFor"
|
|
5
5
|
2014-08-20 v3.1: Addition of values "Reviews" & "IsReviewedBy" and "IsDerivedFrom" & "IsSourceOf"
|
|
6
|
-
2017-10-23
|
|
7
|
-
2019-02-14
|
|
8
|
-
2021-03-05
|
|
6
|
+
2017-10-23 v4.1: Addition of values "Describes", "IsDescribedBy", "HasVersion", "IsVersionOf", "Requires", "IsRequiredBy"
|
|
7
|
+
2019-02-14 v4.2: Addition of values "Obsoletes", "IsObsoletedBy"
|
|
8
|
+
2021-03-05 v4.4: Addition of value "IsPublishedIn"
|
|
9
|
+
2024-01-22 v4.5: Addition of values "Collects, "IsCollectedBy"
|
|
10
|
+
2024-12-31 v4.6: Addition of values "HasTranslation", "IsTranslationOf"-->
|
|
9
11
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://datacite.org/schema/kernel-4" targetNamespace="http://datacite.org/schema/kernel-4" elementFormDefault="qualified">
|
|
10
12
|
<xs:simpleType name="relationType" id="relationType">
|
|
11
13
|
<xs:annotation>
|
|
@@ -48,6 +50,8 @@
|
|
|
48
50
|
<xs:enumeration value="IsObsoletedBy" />
|
|
49
51
|
<xs:enumeration value="Collects" />
|
|
50
52
|
<xs:enumeration value="IsCollectedBy" />
|
|
53
|
+
<xs:enumeration value="HasTranslation" />
|
|
54
|
+
<xs:enumeration value="IsTranslationOf" />
|
|
51
55
|
</xs:restriction>
|
|
52
56
|
</xs:simpleType>
|
|
53
57
|
</xs:schema>
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
2013-05 v3.0: Addition of ID to simpleType element; added values "Audiovisual", "Workflow" & "Other"; deleted value "Film"
|
|
4
4
|
2017-10-23 v4.1: Addition of value "DataPaper"
|
|
5
5
|
2020-01-14 v4.4: Addition of values "Book", "Book Chapter", "ComputationalNotebook", "ConferencePaper", "ConferenceProceeding".
|
|
6
|
-
"Dissertation", "Journal", "JournalArticle", "OutputManagementPlan", "PeerReview", "Preprint", "Report"
|
|
6
|
+
"Dissertation", "Journal", "JournalArticle", "OutputManagementPlan", "PeerReview", "Preprint", "Report"
|
|
7
|
+
2024-01-22 v4.5: Addition of values "Instrument", "StudyRegistration"
|
|
8
|
+
2024-12-31 v4.6: Addition of values "Award", "Project"-->
|
|
7
9
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://datacite.org/schema/kernel-4" targetNamespace="http://datacite.org/schema/kernel-4" elementFormDefault="qualified">
|
|
8
10
|
<xs:simpleType name="resourceType" id="resourceType">
|
|
9
11
|
<xs:annotation>
|
|
@@ -11,6 +13,7 @@
|
|
|
11
13
|
</xs:annotation>
|
|
12
14
|
<xs:restriction base="xs:string">
|
|
13
15
|
<xs:enumeration value="Audiovisual" />
|
|
16
|
+
<xs:enumeration value="Award" />
|
|
14
17
|
<xs:enumeration value="Book" />
|
|
15
18
|
<xs:enumeration value="BookChapter" />
|
|
16
19
|
<xs:enumeration value="Collection" />
|
|
@@ -31,6 +34,7 @@
|
|
|
31
34
|
<xs:enumeration value="PeerReview" />
|
|
32
35
|
<xs:enumeration value="PhysicalObject" />
|
|
33
36
|
<xs:enumeration value="Preprint" />
|
|
37
|
+
<xs:enumeration value="Project" />
|
|
34
38
|
<xs:enumeration value="Report" />
|
|
35
39
|
<xs:enumeration value="Service" />
|
|
36
40
|
<xs:enumeration value="Software" />
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<!-- Version 1.0 - Created 2011-01-13 - FZ, TIB, Germany
|
|
3
3
|
2013-05 v3.0: Addition of ID to simpleType element
|
|
4
|
-
2015-02-12 v4.0 Added value "Other" -->
|
|
4
|
+
2015-02-12 v4.0: Added value "Other" -->
|
|
5
5
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://datacite.org/schema/kernel-4" targetNamespace="http://datacite.org/schema/kernel-4" elementFormDefault="qualified">
|
|
6
6
|
<xs:simpleType name="titleType" id="titleType">
|
|
7
7
|
<xs:restriction base="xs:string">
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
2019-02-14 v4.2: Addition of dateType value "Withdrawn", relationType values "Obsoletes", "isObsoletedBy", addition of new subproperties for Rights: rightsIdentifier, rightsIdentifierScheme, schemeURI, addition of the XML language attribute to the properties Creator, Contributor and Publisher for organizational names, don't check format of DOI
|
|
14
14
|
2019-07-13 v4.3: Addition of new subproperties for Affiliation: "affiliationIdentifier", "affiliationIdentifierScheme", "schemeURI", addition of new sub-property for funderIdentifier: "schemeURI", addition of new funderIdentifierScheme: "ROR", added documentation for nameIdentifier
|
|
15
15
|
2021-03-08 v4.4: Addition of new property relatedItem, relationType value "isPublishedIn", subject subproperty "classificationCode", controlled list "numberType", additional 13 properties for controlled list "resourceType"
|
|
16
|
-
|
|
16
|
+
2024-01-22 v4.5: Addition of new subproperties for publisher: "publisherIdentifier", "publisherIdentifierScheme", and "schemeURI"; addition of new resourceTypeGeneral values "Instrument" and "StudyRegistration"; addition of new relationType values "Collects" and "IsCollectedBy".
|
|
17
|
+
2024-12-31 v4.6: Addition of new resourceTypeGeneral values "Award" and "Project"; addiition of new relatedIdentifierType values "CSTR" and "RRID"; addition of new contributorType "Translator"; addition of new relationTypes "HasTranslation" and "IsTranslationOf"; addition of new dateType "Coverage".-->
|
|
17
18
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://datacite.org/schema/kernel-4" targetNamespace="http://datacite.org/schema/kernel-4" elementFormDefault="qualified" xml:lang="EN">
|
|
18
19
|
<xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="include/xml.xsd" />
|
|
19
20
|
<xs:include schemaLocation="include/datacite-titleType-v4.xsd" />
|