bibframe_ruby 0.1.2 → 0.2.0
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/README.md +24 -2
- data/docs/superpowers/plans/2026-09-09-marc-conversion.md +537 -0
- data/docs/superpowers/specs/2026-09-09-marc-conversion-design.md +110 -0
- data/lib/bibframe_ruby/marc_converter.rb +67 -0
- data/lib/bibframe_ruby/parser.rb +4 -2
- data/lib/bibframe_ruby/version.rb +1 -1
- data/lib/bibframe_ruby.rb +7 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-001-007.xsl +2276 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-006,008.xsl +1295 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-010-048.xsl +1712 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-050-088.xsl +713 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-1XX,7XX,8XX-names.xsl +1141 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-200-247not240-Titles.xsl +771 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-240andX30-UnifTitle.xsl +535 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-250-270.xsl +283 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-3XX.xsl +2245 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-460-468-SeriesTreat.xsl +135 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-490-510-Links.xsl +145 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-5XX.xsl +1448 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-600-662.xsl +1417 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-720+740to755.xsl +333 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-758.xsl +102 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-760-788-Links.xsl +771 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-841-887.xsl +328 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-880.xsl +119 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-ControlSubfields.xsl +495 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-LDR.xsl +183 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-Preprocess0-Splitting.xsl +765 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-Process6-Series.xsl +627 -0
- data/vendor/marc2bibframe2/xsl/ConvSpec-Process8-ProvAct.xsl +1021 -0
- data/vendor/marc2bibframe2/xsl/conf/abbreviations.xml +13 -0
- data/vendor/marc2bibframe2/xsl/conf/code-to-script.xml +399 -0
- data/vendor/marc2bibframe2/xsl/conf/codeMaps.xml +723 -0
- data/vendor/marc2bibframe2/xsl/conf/exclusions.xml +4 -0
- data/vendor/marc2bibframe2/xsl/conf/iso6392-to-1.xml +615 -0
- data/vendor/marc2bibframe2/xsl/conf/languageCrosswalk.xml +1503 -0
- data/vendor/marc2bibframe2/xsl/conf/map880.xml +175 -0
- data/vendor/marc2bibframe2/xsl/conf/scriptCrosswalk.xml +210 -0
- data/vendor/marc2bibframe2/xsl/conf/subjectThesaurus.xml +29 -0
- data/vendor/marc2bibframe2/xsl/marc2bibframe2.xsl +610 -0
- data/vendor/marc2bibframe2/xsl/naco-normalize.xsl +205 -0
- data/vendor/marc2bibframe2/xsl/utils.xsl +963 -0
- data/vendor/marc2bibframe2/xsl/variables.xsl +108 -0
- metadata +68 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# BibframeRuby::MarcConverter: Converts MARC records to BIBFRAME RDF/XML via XSLT
|
|
4
|
+
|
|
5
|
+
require "nokogiri"
|
|
6
|
+
require "marc"
|
|
7
|
+
require "stringio"
|
|
8
|
+
|
|
9
|
+
module BibframeRuby
|
|
10
|
+
# Converts MARC (binary or MARCXML) to BIBFRAME RDF/XML using the vendored marc2bibframe2 XSLT.
|
|
11
|
+
class MarcConverter
|
|
12
|
+
XSL_DIR = File.expand_path("../../vendor/marc2bibframe2/xsl", __dir__)
|
|
13
|
+
XSL_PATH = File.join(XSL_DIR, "marc2bibframe2.xsl")
|
|
14
|
+
# Mutex to serialise Dir.chdir calls — Dir.chdir is process-global and not thread-safe.
|
|
15
|
+
CHDIR_MUTEX = Mutex.new
|
|
16
|
+
|
|
17
|
+
def initialize(input, baseuri: "http://example.org/", idsource: "http://id.loc.gov/vocabulary/organizations/dlc")
|
|
18
|
+
@input = input
|
|
19
|
+
@baseuri = baseuri
|
|
20
|
+
@idsource = idsource
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def convert
|
|
24
|
+
xml = self.class.marcxml?(@input) ? @input : binary_to_marcxml(@input)
|
|
25
|
+
doc = Nokogiri::XML(xml)
|
|
26
|
+
rdfxml = transform(doc)
|
|
27
|
+
rdfxml.to_xml
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.marcxml?(input)
|
|
31
|
+
input.lstrip.start_with?("<")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def binary_to_marcxml(input)
|
|
37
|
+
reader = MARC::Reader.new(StringIO.new(input))
|
|
38
|
+
output = StringIO.new
|
|
39
|
+
writer = MARC::XMLWriter.new(output)
|
|
40
|
+
reader.each { |record| writer.write(record) }
|
|
41
|
+
writer.close
|
|
42
|
+
output.string
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def transform(doc)
|
|
46
|
+
params = ["baseuri", "\"#{@baseuri}\""]
|
|
47
|
+
params += ["idsource", "\"#{@idsource}\""] if @idsource
|
|
48
|
+
|
|
49
|
+
# Ensure the stylesheet is loaded (and its Dir.chdir released) before we
|
|
50
|
+
# acquire CHDIR_MUTEX again for the transform call.
|
|
51
|
+
sheet = self.class.stylesheet
|
|
52
|
+
CHDIR_MUTEX.synchronize do
|
|
53
|
+
Dir.chdir(XSL_DIR) do
|
|
54
|
+
sheet.transform(doc, params)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.stylesheet
|
|
60
|
+
@stylesheet ||= CHDIR_MUTEX.synchronize do
|
|
61
|
+
Dir.chdir(XSL_DIR) do
|
|
62
|
+
Nokogiri::XSLT(File.read(XSL_PATH))
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
data/lib/bibframe_ruby/parser.rb
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
require "json/ld"
|
|
4
4
|
require "rdf"
|
|
5
5
|
require "rdf/turtle"
|
|
6
|
+
require "rdf/rdfxml"
|
|
6
7
|
|
|
7
8
|
# BibframeRuby::Parser: Converts serialized RDF input into an RDF graph
|
|
8
9
|
module BibframeRuby
|
|
9
|
-
# Parses serialized RDF input (JSON-LD, Turtle) into an RDF::Graph using the appropriate reader.
|
|
10
|
+
# Parses serialized RDF input (JSON-LD, Turtle, RDF/XML) into an RDF::Graph using the appropriate reader.
|
|
10
11
|
class Parser
|
|
11
12
|
EXTENSION_MAP = {
|
|
12
13
|
".jsonld" => :jsonld,
|
|
@@ -16,7 +17,8 @@ module BibframeRuby
|
|
|
16
17
|
|
|
17
18
|
READER_MAP = {
|
|
18
19
|
jsonld: JSON::LD::Reader,
|
|
19
|
-
turtle: RDF::Turtle::Reader
|
|
20
|
+
turtle: RDF::Turtle::Reader,
|
|
21
|
+
rdfxml: RDF::RDFXML::Reader
|
|
20
22
|
}.freeze
|
|
21
23
|
|
|
22
24
|
def initialize(input, format: :jsonld)
|
data/lib/bibframe_ruby.rb
CHANGED
|
@@ -17,6 +17,7 @@ require_relative "bibframe_ruby/models/hub"
|
|
|
17
17
|
require_relative "bibframe_ruby/parser"
|
|
18
18
|
require_relative "bibframe_ruby/graph_builder"
|
|
19
19
|
require_relative "bibframe_ruby/graph"
|
|
20
|
+
require_relative "bibframe_ruby/marc_converter"
|
|
20
21
|
|
|
21
22
|
# BibframeRuby: Main entry point for parsing BIBFRAME data into Ruby objects
|
|
22
23
|
module BibframeRuby
|
|
@@ -34,6 +35,12 @@ module BibframeRuby
|
|
|
34
35
|
parse(input, format: format)
|
|
35
36
|
end
|
|
36
37
|
|
|
38
|
+
def self.convert_marc(path, baseuri: "http://example.org/", idsource: "http://id.loc.gov/vocabulary/organizations/dlc")
|
|
39
|
+
input = File.read(path)
|
|
40
|
+
rdfxml = MarcConverter.new(input, baseuri: baseuri, idsource: idsource).convert
|
|
41
|
+
parse(rdfxml, format: :rdfxml)
|
|
42
|
+
end
|
|
43
|
+
|
|
37
44
|
def self.parse_uri(uri, redirect_limit: 5)
|
|
38
45
|
raise Error, "Too many redirects" if redirect_limit.zero?
|
|
39
46
|
|