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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -2
  3. data/docs/superpowers/plans/2026-09-09-marc-conversion.md +537 -0
  4. data/docs/superpowers/specs/2026-09-09-marc-conversion-design.md +110 -0
  5. data/lib/bibframe_ruby/marc_converter.rb +67 -0
  6. data/lib/bibframe_ruby/parser.rb +4 -2
  7. data/lib/bibframe_ruby/version.rb +1 -1
  8. data/lib/bibframe_ruby.rb +7 -0
  9. data/vendor/marc2bibframe2/xsl/ConvSpec-001-007.xsl +2276 -0
  10. data/vendor/marc2bibframe2/xsl/ConvSpec-006,008.xsl +1295 -0
  11. data/vendor/marc2bibframe2/xsl/ConvSpec-010-048.xsl +1712 -0
  12. data/vendor/marc2bibframe2/xsl/ConvSpec-050-088.xsl +713 -0
  13. data/vendor/marc2bibframe2/xsl/ConvSpec-1XX,7XX,8XX-names.xsl +1141 -0
  14. data/vendor/marc2bibframe2/xsl/ConvSpec-200-247not240-Titles.xsl +771 -0
  15. data/vendor/marc2bibframe2/xsl/ConvSpec-240andX30-UnifTitle.xsl +535 -0
  16. data/vendor/marc2bibframe2/xsl/ConvSpec-250-270.xsl +283 -0
  17. data/vendor/marc2bibframe2/xsl/ConvSpec-3XX.xsl +2245 -0
  18. data/vendor/marc2bibframe2/xsl/ConvSpec-460-468-SeriesTreat.xsl +135 -0
  19. data/vendor/marc2bibframe2/xsl/ConvSpec-490-510-Links.xsl +145 -0
  20. data/vendor/marc2bibframe2/xsl/ConvSpec-5XX.xsl +1448 -0
  21. data/vendor/marc2bibframe2/xsl/ConvSpec-600-662.xsl +1417 -0
  22. data/vendor/marc2bibframe2/xsl/ConvSpec-720+740to755.xsl +333 -0
  23. data/vendor/marc2bibframe2/xsl/ConvSpec-758.xsl +102 -0
  24. data/vendor/marc2bibframe2/xsl/ConvSpec-760-788-Links.xsl +771 -0
  25. data/vendor/marc2bibframe2/xsl/ConvSpec-841-887.xsl +328 -0
  26. data/vendor/marc2bibframe2/xsl/ConvSpec-880.xsl +119 -0
  27. data/vendor/marc2bibframe2/xsl/ConvSpec-ControlSubfields.xsl +495 -0
  28. data/vendor/marc2bibframe2/xsl/ConvSpec-LDR.xsl +183 -0
  29. data/vendor/marc2bibframe2/xsl/ConvSpec-Preprocess0-Splitting.xsl +765 -0
  30. data/vendor/marc2bibframe2/xsl/ConvSpec-Process6-Series.xsl +627 -0
  31. data/vendor/marc2bibframe2/xsl/ConvSpec-Process8-ProvAct.xsl +1021 -0
  32. data/vendor/marc2bibframe2/xsl/conf/abbreviations.xml +13 -0
  33. data/vendor/marc2bibframe2/xsl/conf/code-to-script.xml +399 -0
  34. data/vendor/marc2bibframe2/xsl/conf/codeMaps.xml +723 -0
  35. data/vendor/marc2bibframe2/xsl/conf/exclusions.xml +4 -0
  36. data/vendor/marc2bibframe2/xsl/conf/iso6392-to-1.xml +615 -0
  37. data/vendor/marc2bibframe2/xsl/conf/languageCrosswalk.xml +1503 -0
  38. data/vendor/marc2bibframe2/xsl/conf/map880.xml +175 -0
  39. data/vendor/marc2bibframe2/xsl/conf/scriptCrosswalk.xml +210 -0
  40. data/vendor/marc2bibframe2/xsl/conf/subjectThesaurus.xml +29 -0
  41. data/vendor/marc2bibframe2/xsl/marc2bibframe2.xsl +610 -0
  42. data/vendor/marc2bibframe2/xsl/naco-normalize.xsl +205 -0
  43. data/vendor/marc2bibframe2/xsl/utils.xsl +963 -0
  44. data/vendor/marc2bibframe2/xsl/variables.xsl +108 -0
  45. 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
@@ -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)
@@ -2,5 +2,5 @@
2
2
 
3
3
  # BibframeRuby::VERSION: Gem version constant
4
4
  module BibframeRuby
5
- VERSION = "0.1.2"
5
+ VERSION = "0.2.0"
6
6
  end
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