metacrunch-mab2 1.2.1-universal-java-1.8
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 +7 -0
- data/.gitignore +24 -0
- data/.rspec +3 -0
- data/.travis.yml +4 -0
- data/Gemfile +21 -0
- data/License.txt +22 -0
- data/Rakefile +6 -0
- data/Readme.md +6 -0
- data/bin/console +14 -0
- data/lib/metacrunch/mab2/builder.rb +52 -0
- data/lib/metacrunch/mab2/cli.rb +1 -0
- data/lib/metacrunch/mab2/document/controlfield.rb +91 -0
- data/lib/metacrunch/mab2/document/datafield.rb +69 -0
- data/lib/metacrunch/mab2/document/datafield_set.rb +67 -0
- data/lib/metacrunch/mab2/document/jruby/mab_xml_parser.rb +45 -0
- data/lib/metacrunch/mab2/document/mab_xml_parser.rb +75 -0
- data/lib/metacrunch/mab2/document/subfield.rb +25 -0
- data/lib/metacrunch/mab2/document/subfield_set.rb +59 -0
- data/lib/metacrunch/mab2/document.rb +134 -0
- data/lib/metacrunch/mab2/version.rb +5 -0
- data/lib/metacrunch/mab2/xml_builder.rb +48 -0
- data/lib/metacrunch/mab2.rb +15 -0
- data/metacrunch-mab2.gemspec +33 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bb39868bb9fa32a9babc6108efcee48c3c863c2e
|
4
|
+
data.tar.gz: e863ea0beeb4f34e01afff66c7ed67e20d8a6720
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2e7cf09fdb473a8f80c033076ee45b67a64943558141968f602cae6f43c56de5357cce461462edeeb816c13c9d53d2ba3d90e80191f31dd13c5d435af817f2ee
|
7
|
+
data.tar.gz: eb9c8a71b21661df4447074665f3a81a3daa4dec8a484747a4a058f130337ecc00ff8c700dbbb8f77b2f205a656b02b3bfd33a95ca31039310ea9f88e28cd677
|
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
.DS_Store
|
2
|
+
/doc
|
3
|
+
*.gem
|
4
|
+
*.rbc
|
5
|
+
.bundle
|
6
|
+
.config
|
7
|
+
.yardoc
|
8
|
+
Gemfile.lock
|
9
|
+
InstalledFiles
|
10
|
+
_yardoc
|
11
|
+
coverage
|
12
|
+
doc/
|
13
|
+
lib/bundler/man
|
14
|
+
pkg
|
15
|
+
rdoc
|
16
|
+
spec/reports
|
17
|
+
test/tmp
|
18
|
+
test/version_tmp
|
19
|
+
tmp
|
20
|
+
*.bundle
|
21
|
+
*.so
|
22
|
+
*.o
|
23
|
+
*.a
|
24
|
+
mkmf.log
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
gem "bundler", ">= 1.7"
|
7
|
+
gem "rake", ">= 11.1"
|
8
|
+
gem "rspec", ">= 3.0.0", "< 4.0.0"
|
9
|
+
gem "simplecov", ">= 0.11.0"
|
10
|
+
|
11
|
+
if !ENV["CI"]
|
12
|
+
gem "hashdiff", ">= 0.3.0", platform: :ruby
|
13
|
+
gem "pry-byebug", ">= 3.3.0", platform: :ruby
|
14
|
+
gem "pry-rescue", ">= 1.4.2", platform: :ruby
|
15
|
+
gem "pry-state", ">= 0.1.7", platform: :ruby
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
group :test do
|
20
|
+
gem "codeclimate-test-reporter", ">= 0.5.0", require: nil
|
21
|
+
end
|
data/License.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 René Sprotte, Michael Sievers, Marcel Otto
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
# metacrunch-mab2
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/ubpb/metacrunch-mab2)
|
4
|
+
[](https://travis-ci.org/ubpb/metacrunch-mab2)
|
5
|
+
|
6
|
+
Dokumentation folgt in Kürze...
|
data/bin/console
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative "./document"
|
2
|
+
|
3
|
+
module Metacrunch
|
4
|
+
module Mab2
|
5
|
+
class Builder
|
6
|
+
|
7
|
+
attr_reader :document
|
8
|
+
|
9
|
+
def self.build(&block)
|
10
|
+
builder = new
|
11
|
+
document = builder.instance_eval(&block) if block_given?
|
12
|
+
document || Document.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@document = Document.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def controlfield(tag, values)
|
20
|
+
controlfield = Document::Controlfield.new(tag, values)
|
21
|
+
@document.add_controlfield(controlfield)
|
22
|
+
@document
|
23
|
+
end
|
24
|
+
|
25
|
+
def datafield(tag, ind1:nil, ind2:nil, &block)
|
26
|
+
datafield = Document::Datafield.new(tag, ind1: ind1, ind2: ind2)
|
27
|
+
@document.add_datafield(datafield)
|
28
|
+
|
29
|
+
if block_given?
|
30
|
+
subfield_builder = SubfieldBuilder.new(datafield)
|
31
|
+
subfield_builder.instance_eval(&block)
|
32
|
+
end
|
33
|
+
|
34
|
+
@document
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
class SubfieldBuilder
|
39
|
+
def initialize(datafield)
|
40
|
+
@datafield = datafield
|
41
|
+
end
|
42
|
+
|
43
|
+
def subfield(code, value)
|
44
|
+
subfield = Document::Subfield.new(code, value)
|
45
|
+
@datafield.add_subfield(subfield)
|
46
|
+
subfield
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# TODO
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Metacrunch
|
2
|
+
module Mab2
|
3
|
+
class Document
|
4
|
+
class Controlfield
|
5
|
+
|
6
|
+
attr_accessor :tag
|
7
|
+
|
8
|
+
def initialize(tag = nil, values = [])
|
9
|
+
self.tag = tag
|
10
|
+
self.values = values
|
11
|
+
end
|
12
|
+
|
13
|
+
def tag=(value)
|
14
|
+
@tag = value.to_s if value
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Setter for the control field values. Values can be given as String or
|
19
|
+
# as an Array.
|
20
|
+
#
|
21
|
+
# @param [String, Array] values for the control field as a String or Array.
|
22
|
+
# In case of String the MAB2 delimiter/placeholder | is respected. In case
|
23
|
+
# of an Array every element is converted into a String. Empty strings are
|
24
|
+
# converted into nil. Array values that are longer than one character will
|
25
|
+
# raise an ArgumentError.
|
26
|
+
#
|
27
|
+
# @example Add control field using String values
|
28
|
+
# add_control_field("050", "a|b||")
|
29
|
+
#
|
30
|
+
# @example Add control field using Array
|
31
|
+
# add_control_field("050", ["a", nil, "b", nil, nil])
|
32
|
+
#
|
33
|
+
def values=(values)
|
34
|
+
@values = case values
|
35
|
+
when String then string2values(values)
|
36
|
+
when Array then array2values(values)
|
37
|
+
when nil then []
|
38
|
+
else
|
39
|
+
raise ArgumentError, "expecting a String or Array, but got #{values}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# @return [Array<String>]
|
45
|
+
#
|
46
|
+
def values
|
47
|
+
@values
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# @param [int] index
|
52
|
+
# @return [Array<String>] value at given index
|
53
|
+
#
|
54
|
+
def at(index)
|
55
|
+
@values.at(index)
|
56
|
+
end
|
57
|
+
|
58
|
+
# ------------------------------------------------------------------------------
|
59
|
+
# Serialization
|
60
|
+
# ------------------------------------------------------------------------------
|
61
|
+
|
62
|
+
def to_xml(builder)
|
63
|
+
builder.controlfield(values2string, tag: tag)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def string2values(string)
|
69
|
+
string.chars.to_a.map{ |e| (e=="|") ? nil : e }
|
70
|
+
end
|
71
|
+
|
72
|
+
def array2values(array)
|
73
|
+
array.map do |v|
|
74
|
+
if v.present?
|
75
|
+
v = v.to_s
|
76
|
+
raise ArgumentError, "invalid value of controlfield #{tag}: #{array}" if v.length > 1
|
77
|
+
v
|
78
|
+
else
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def values2string
|
85
|
+
values.map{|c| c.blank? ? "|" : c}.join
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Metacrunch
|
2
|
+
module Mab2
|
3
|
+
class Document
|
4
|
+
class Datafield
|
5
|
+
|
6
|
+
attr_accessor :tag
|
7
|
+
attr_accessor :ind1, :ind2
|
8
|
+
|
9
|
+
def initialize(tag = nil, ind1:nil, ind2:nil)
|
10
|
+
@tag = tag
|
11
|
+
@ind1 = ind1
|
12
|
+
@ind2 = ind2
|
13
|
+
@subfields = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def value
|
17
|
+
subfields.value
|
18
|
+
end
|
19
|
+
|
20
|
+
# ------------------------------------------------------------------------------
|
21
|
+
# Sub fields
|
22
|
+
# ------------------------------------------------------------------------------
|
23
|
+
|
24
|
+
#
|
25
|
+
# Returns the sub field matching the given code.
|
26
|
+
#
|
27
|
+
# @param [String] code of the sub field
|
28
|
+
# @return [Metacrunch::Mab2::Document::SubfieldSet] sub field with the given code. The set
|
29
|
+
# is empty if the sub field doesn't exists.
|
30
|
+
#
|
31
|
+
def subfields(code = nil)
|
32
|
+
result = Metacrunch::Mab2::Document::SubfieldSet.new
|
33
|
+
|
34
|
+
if code.nil?
|
35
|
+
result.concat(@subfields.values.flatten(1))
|
36
|
+
elsif _subfields = @subfields[code]
|
37
|
+
result.concat(_subfields)
|
38
|
+
elsif (codes = code).is_a?(Array)
|
39
|
+
result.concat(codes.map { |_code| @subfields[_code] }.compact.flatten(1))
|
40
|
+
end
|
41
|
+
|
42
|
+
result
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Adds a new sub field.
|
47
|
+
#
|
48
|
+
# @param [Metacrunch::Mab2::Document::Subfield] subfield
|
49
|
+
#
|
50
|
+
def add_subfield(subfield)
|
51
|
+
(@subfields[subfield.code] ||= []) << subfield
|
52
|
+
end
|
53
|
+
|
54
|
+
# ------------------------------------------------------------------------------
|
55
|
+
# Serialization
|
56
|
+
# ------------------------------------------------------------------------------
|
57
|
+
|
58
|
+
def to_xml(builder)
|
59
|
+
builder.datafield(tag: tag, ind1: ind1, ind2: ind2) do
|
60
|
+
@subfields.values.each do |_subfield_set|
|
61
|
+
_subfield_set.to_xml(builder)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "self_enumerable"
|
2
|
+
|
3
|
+
module Metacrunch
|
4
|
+
module Mab2
|
5
|
+
class Document
|
6
|
+
class DatafieldSet
|
7
|
+
include SelfEnumerable
|
8
|
+
|
9
|
+
def initialize(datafields = [])
|
10
|
+
@datafields = datafields
|
11
|
+
end
|
12
|
+
|
13
|
+
def each
|
14
|
+
block_given? ? @datafields.each { |_datafield| yield _datafield } : to_enum
|
15
|
+
end
|
16
|
+
|
17
|
+
def <<(datafield)
|
18
|
+
@datafields << datafield
|
19
|
+
end
|
20
|
+
|
21
|
+
def concat(datafield_set)
|
22
|
+
@datafields.concat(datafield_set.to_a)
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def value
|
27
|
+
@datafields.find { |_datafield| _datafield.value }.try(:value)
|
28
|
+
end
|
29
|
+
alias_method :first_value, :value
|
30
|
+
|
31
|
+
def to_a
|
32
|
+
@datafields
|
33
|
+
end
|
34
|
+
|
35
|
+
def empty?
|
36
|
+
@datafields.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
def present?
|
40
|
+
!empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Metacrunch::Mab2::Document::SubfieldSet]
|
44
|
+
def subfields(code = nil)
|
45
|
+
result = Metacrunch::Mab2::Document::SubfieldSet.new
|
46
|
+
|
47
|
+
@datafields.each do |_datafield|
|
48
|
+
result.concat(_datafield.subfields(code))
|
49
|
+
end
|
50
|
+
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
# ------------------------------------------------------------------------------
|
55
|
+
# Serialization
|
56
|
+
# ------------------------------------------------------------------------------
|
57
|
+
|
58
|
+
def to_xml(builder)
|
59
|
+
self.each do |_datafield|
|
60
|
+
_datafield.to_xml(builder)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Metacrunch
|
2
|
+
module Mab2
|
3
|
+
class Document
|
4
|
+
class MabXmlParser
|
5
|
+
|
6
|
+
def parse(mab_xml)
|
7
|
+
xml = Nokogiri::XML(mab_xml.try(:strip))
|
8
|
+
xml.remove_namespaces!
|
9
|
+
|
10
|
+
html_entities = HTMLEntities.new
|
11
|
+
document = Document.new
|
12
|
+
|
13
|
+
xml.xpath("//metadata/record").children.each do |node|
|
14
|
+
if node.name == "controlfield"
|
15
|
+
controlfield = Metacrunch::Mab2::Document::Controlfield.new
|
16
|
+
controlfield.tag = node.attributes["tag"].value
|
17
|
+
controlfield.values = node.content
|
18
|
+
document.add_controlfield(controlfield)
|
19
|
+
elsif node.name == "datafield" then
|
20
|
+
datafield = Metacrunch::Mab2::Document::Datafield.new
|
21
|
+
datafield.tag = node.attributes["tag"].value
|
22
|
+
datafield.ind1 = node.attributes["ind1"].try(:value)
|
23
|
+
datafield.ind2 = node.attributes["ind2"].try(:value)
|
24
|
+
|
25
|
+
node.children.each do |subnode|
|
26
|
+
if subnode.name == "subfield"
|
27
|
+
subfield = Metacrunch::Mab2::Document::Subfield.new
|
28
|
+
subfield.code = subnode.attributes["code"].value
|
29
|
+
value = subnode.content
|
30
|
+
subfield.value = value.include?("&") ? html_entities.decode(value) : value
|
31
|
+
datafield.add_subfield(subfield)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
document.add_datafield(datafield)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
document
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "ox"
|
2
|
+
|
3
|
+
module Metacrunch
|
4
|
+
module Mab2
|
5
|
+
class Document
|
6
|
+
class MabXmlParser < Ox::Sax
|
7
|
+
|
8
|
+
def parse(mab_xml)
|
9
|
+
# initialize state machine
|
10
|
+
@in_controlfield = @in_datafield = @in_subfield = false
|
11
|
+
|
12
|
+
@controlfield = @datafield = @subfield = nil
|
13
|
+
@document = Document.new
|
14
|
+
@html_entities_coder = HTMLEntities.new
|
15
|
+
|
16
|
+
# convert_special tells ox to convert some html entities already during
|
17
|
+
# parsing, which minifies the amount of entities we have to decode ourself
|
18
|
+
Ox.sax_parse(self, mab_xml, convert_special: true)
|
19
|
+
|
20
|
+
return @document
|
21
|
+
end
|
22
|
+
|
23
|
+
def start_element(name)
|
24
|
+
if name == :subfield
|
25
|
+
@in_subfield = true
|
26
|
+
@subfield = Metacrunch::Mab2::Document::Subfield.new
|
27
|
+
elsif name == :datafield
|
28
|
+
@in_datafield = true
|
29
|
+
@datafield = Metacrunch::Mab2::Document::Datafield.new
|
30
|
+
elsif name == :controlfield
|
31
|
+
@in_controlfield = true
|
32
|
+
@controlfield = Metacrunch::Mab2::Document::Controlfield.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def end_element(name)
|
37
|
+
if @in_subfield
|
38
|
+
@in_subfield = false
|
39
|
+
@datafield.add_subfield(@subfield)
|
40
|
+
elsif @in_datafield
|
41
|
+
@in_datafield = false
|
42
|
+
@document.add_datafield(@datafield)
|
43
|
+
elsif @in_controlfield
|
44
|
+
@in_controlfield = false
|
45
|
+
@document.add_controlfield(@controlfield)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def attr(name, value)
|
50
|
+
if @in_subfield
|
51
|
+
@subfield.code = value if name == :code
|
52
|
+
elsif @in_datafield
|
53
|
+
if name == :tag
|
54
|
+
@datafield.tag = value
|
55
|
+
elsif name == :ind1
|
56
|
+
@datafield.ind1 = value
|
57
|
+
elsif name == :ind2
|
58
|
+
@datafield.ind2 = value
|
59
|
+
end
|
60
|
+
elsif @in_controlfield
|
61
|
+
@controlfield.tag = value if name == :tag
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def text(value)
|
66
|
+
if @in_subfield
|
67
|
+
@subfield.value = value.include?("&") ? @html_entities_coder.decode(value) : value
|
68
|
+
elsif @in_controlfield
|
69
|
+
@controlfield.values = value
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Metacrunch
|
2
|
+
module Mab2
|
3
|
+
class Document
|
4
|
+
class Subfield
|
5
|
+
|
6
|
+
attr_accessor :code
|
7
|
+
attr_accessor :value
|
8
|
+
|
9
|
+
def initialize(code = nil, value = nil)
|
10
|
+
@code = code
|
11
|
+
@value = value
|
12
|
+
end
|
13
|
+
|
14
|
+
# ------------------------------------------------------------------------------
|
15
|
+
# Serialization
|
16
|
+
# ------------------------------------------------------------------------------
|
17
|
+
|
18
|
+
def to_xml(builder)
|
19
|
+
builder.subfield(value, code: code)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "self_enumerable"
|
2
|
+
|
3
|
+
module Metacrunch
|
4
|
+
module Mab2
|
5
|
+
class Document
|
6
|
+
class SubfieldSet
|
7
|
+
include SelfEnumerable
|
8
|
+
|
9
|
+
def initialize(subfields = [])
|
10
|
+
@subfields = subfields
|
11
|
+
end
|
12
|
+
|
13
|
+
def each
|
14
|
+
block_given? ? @subfields.each { |_subfield| yield _subfield } : to_enum
|
15
|
+
end
|
16
|
+
|
17
|
+
def <<(subfield)
|
18
|
+
@subfields << subfield
|
19
|
+
end
|
20
|
+
|
21
|
+
def concat(subfield_set)
|
22
|
+
@subfields.concat(subfield_set.to_a)
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_a
|
26
|
+
@subfields
|
27
|
+
end
|
28
|
+
|
29
|
+
def empty?
|
30
|
+
@subfields.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
def present?
|
34
|
+
!empty?
|
35
|
+
end
|
36
|
+
|
37
|
+
def value
|
38
|
+
values.find{ |v| v.present? }
|
39
|
+
end
|
40
|
+
alias_method :first_value, :value
|
41
|
+
|
42
|
+
def values
|
43
|
+
@subfields.map{ |subfield| subfield.value }
|
44
|
+
end
|
45
|
+
|
46
|
+
# ------------------------------------------------------------------------------
|
47
|
+
# Serialization
|
48
|
+
# ------------------------------------------------------------------------------
|
49
|
+
|
50
|
+
def to_xml(builder)
|
51
|
+
self.each do |_subfield|
|
52
|
+
_subfield.to_xml(builder)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module Metacrunch
|
2
|
+
module Mab2
|
3
|
+
class Document
|
4
|
+
if RUBY_PLATFORM == "java"
|
5
|
+
require_relative "document/jruby/mab_xml_parser"
|
6
|
+
else
|
7
|
+
require_relative "document/mab_xml_parser"
|
8
|
+
end
|
9
|
+
|
10
|
+
require_relative "document/controlfield"
|
11
|
+
require_relative "document/datafield"
|
12
|
+
require_relative "document/datafield_set"
|
13
|
+
require_relative "document/subfield"
|
14
|
+
require_relative "document/subfield_set"
|
15
|
+
|
16
|
+
# ------------------------------------------------------------------------------
|
17
|
+
# Parsing
|
18
|
+
# ------------------------------------------------------------------------------
|
19
|
+
|
20
|
+
#
|
21
|
+
# @param [String] xml repesenting a MAB document in Aleph MAB XML format
|
22
|
+
# @return [Metacrunch::Mab2::Document]
|
23
|
+
#
|
24
|
+
def self.from_aleph_mab_xml(xml)
|
25
|
+
MabXmlParser.new.parse(xml)
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@controlfields = {}
|
30
|
+
@datafields = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
# ------------------------------------------------------------------------------
|
34
|
+
# Control fields
|
35
|
+
# ------------------------------------------------------------------------------
|
36
|
+
|
37
|
+
#
|
38
|
+
# Returns the control field matching the given tag.
|
39
|
+
#
|
40
|
+
# @param [String] tag of the control field
|
41
|
+
# @return [Controlfield] control field with the given tag.
|
42
|
+
#
|
43
|
+
def controlfield(tag)
|
44
|
+
@controlfields[tag] || Controlfield.new(tag)
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Adds a new control field.
|
49
|
+
#
|
50
|
+
# @param [Metacrunch::Mab2::Document::Controlfield] controlfield
|
51
|
+
#
|
52
|
+
def add_controlfield(controlfield)
|
53
|
+
@controlfields[controlfield.tag] = controlfield
|
54
|
+
end
|
55
|
+
|
56
|
+
# ------------------------------------------------------------------------------
|
57
|
+
# Data fields
|
58
|
+
# ------------------------------------------------------------------------------
|
59
|
+
|
60
|
+
#
|
61
|
+
# Returns the data fields matching the given tag and ind1/ind2.
|
62
|
+
#
|
63
|
+
# @param [String, nil] tag of the data field. Can be nil to match any data field.
|
64
|
+
# @param [String, nil] ind1 filter for ind1. Can be nil to match any indicator 1.
|
65
|
+
# @param [String, nil] ind2 filter for ind2. Can be nil to match any indicator 2.
|
66
|
+
# @return [Metacrunch::Mab2::Document::DatafieldSet] data field with the given tag and ind1/ind2.
|
67
|
+
# The set is empty if a matching field with the tag and/or ind1/ind2 doesn't exists.
|
68
|
+
#
|
69
|
+
def datafields(tag = nil, ind1: nil, ind2: nil)
|
70
|
+
if tag.nil?
|
71
|
+
DatafieldSet.new(@datafields.values.flatten(1))
|
72
|
+
else
|
73
|
+
set = DatafieldSet.new(@datafields[tag] || [])
|
74
|
+
return set if set.empty? || (ind1.nil? && ind2.nil?)
|
75
|
+
|
76
|
+
ind1 = map_indicator(ind1)
|
77
|
+
ind2 = map_indicator(ind2)
|
78
|
+
|
79
|
+
set.select do |_datafield|
|
80
|
+
check_indicator(ind1, _datafield.ind1) && check_indicator(ind2, _datafield.ind2)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Adds a new data field.
|
87
|
+
#
|
88
|
+
# @param [Metacrunch::Mab2::Document::Datafield] datafield
|
89
|
+
#
|
90
|
+
def add_datafield(datafield)
|
91
|
+
(@datafields[datafield.tag] ||= []) << datafield
|
92
|
+
end
|
93
|
+
|
94
|
+
# ------------------------------------------------------------------------------
|
95
|
+
# Serialization
|
96
|
+
# ------------------------------------------------------------------------------
|
97
|
+
|
98
|
+
def to_xml
|
99
|
+
builder = ::Builder::XmlMarkup.new(indent: 2)
|
100
|
+
builder.instruct!(:xml, :encoding => "UTF-8")
|
101
|
+
builder.mab_xml do
|
102
|
+
controlfields_struct.values.each do |_controlfield|
|
103
|
+
_controlfield.to_xml(builder)
|
104
|
+
end
|
105
|
+
|
106
|
+
@datafields.values.each do |_datafield_set|
|
107
|
+
_datafield_set.to_xml(builder)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def map_indicator(ind)
|
115
|
+
ind.is_a?(Array) ? ind.map { |_el| _el == :blank ? [" ", "-", nil] : _el }.flatten(1) : ind
|
116
|
+
end
|
117
|
+
|
118
|
+
def check_indicator(requested_ind, datafield_ind)
|
119
|
+
if !requested_ind
|
120
|
+
true
|
121
|
+
elsif requested_ind == :blank && (datafield_ind == " " || datafield_ind == "-" || datafield_ind.nil?)
|
122
|
+
true
|
123
|
+
elsif requested_ind == datafield_ind
|
124
|
+
true
|
125
|
+
elsif requested_ind.is_a?(Array) && requested_ind.include?(datafield_ind)
|
126
|
+
true
|
127
|
+
else
|
128
|
+
false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "nokogiri"
|
2
|
+
require_relative "../mab2"
|
3
|
+
|
4
|
+
class Metacrunch::Mab2::XmlBuilder
|
5
|
+
def initialize(identifier = nil, &block)
|
6
|
+
@builder =
|
7
|
+
Nokogiri::XML::Builder.new do
|
8
|
+
send(
|
9
|
+
:"OAI-PMH",
|
10
|
+
"xmlns" => "http://www.openarchives.org/OAI/2.0/",
|
11
|
+
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
|
12
|
+
"xsi:schemaLocation" => "http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd"
|
13
|
+
) do
|
14
|
+
ListRecords do
|
15
|
+
record do
|
16
|
+
if identifier
|
17
|
+
header do |_xml|
|
18
|
+
_xml.identifier identifier
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
metadata do
|
23
|
+
record("xmlns" => "http://www.ddb.de/professionell/mabxml/mabxml-1.xsd") do
|
24
|
+
define_singleton_method(:controlfield) do |_tag, _text|
|
25
|
+
send(:method_missing, :controlfield, _text, tag: _tag)
|
26
|
+
end
|
27
|
+
|
28
|
+
define_singleton_method(:datafield) do |_tag, _attributes = {}, &_block|
|
29
|
+
send(:method_missing, :datafield, {tag: _tag}.merge(_attributes), &_block)
|
30
|
+
end
|
31
|
+
|
32
|
+
define_singleton_method(:subfield) do |_code, _text|
|
33
|
+
send(:method_missing, :subfield, _text, code: _code)
|
34
|
+
end
|
35
|
+
|
36
|
+
instance_eval(&block)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_xml
|
46
|
+
@builder.to_xml
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "active_support"
|
3
|
+
require "active_support/core_ext"
|
4
|
+
require "htmlentities"
|
5
|
+
require "nokogiri"
|
6
|
+
require "ox" unless RUBY_PLATFORM == "java"
|
7
|
+
|
8
|
+
module Metacrunch
|
9
|
+
module Mab2
|
10
|
+
require_relative "./mab2/builder"
|
11
|
+
require_relative "./mab2/cli"
|
12
|
+
require_relative "./mab2/document"
|
13
|
+
require_relative "./mab2/version"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "metacrunch/mab2/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "metacrunch-mab2"
|
8
|
+
spec.version = Metacrunch::Mab2::VERSION
|
9
|
+
spec.authors = ["René Sprotte", "Michael Sievers", "Marcel Otto"]
|
10
|
+
spec.email = "r.sprotte@ub.uni-paderborn.de"
|
11
|
+
spec.summary = %q{MAB2 tools for metacrunch}
|
12
|
+
spec.homepage = "http://github.com/ubpb/metacrunch-mab2"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
|
+
spec.bindir = "exe"
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "activesupport", "~> 4.2"
|
21
|
+
spec.add_dependency "htmlentities", "~> 4.3"
|
22
|
+
spec.add_dependency "nokogiri", "~> 1.6"
|
23
|
+
spec.add_dependency "self_enumerable", "~> 0.2"
|
24
|
+
|
25
|
+
if RUBY_PLATFORM != "java"
|
26
|
+
spec.add_dependency "ox", "~> 2.1"
|
27
|
+
end
|
28
|
+
|
29
|
+
if RUBY_PLATFORM == "java"
|
30
|
+
spec.platform = Gem::Platform::CURRENT
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: metacrunch-mab2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.1
|
5
|
+
platform: universal-java-1.8
|
6
|
+
authors:
|
7
|
+
- René Sprotte
|
8
|
+
- Michael Sievers
|
9
|
+
- Marcel Otto
|
10
|
+
autorequire:
|
11
|
+
bindir: exe
|
12
|
+
cert_chain: []
|
13
|
+
date: 2016-04-25 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '4.2'
|
21
|
+
name: activesupport
|
22
|
+
prerelease: false
|
23
|
+
type: :runtime
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - "~>"
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '4.2'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '4.3'
|
35
|
+
name: htmlentities
|
36
|
+
prerelease: false
|
37
|
+
type: :runtime
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '4.3'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.6'
|
49
|
+
name: nokogiri
|
50
|
+
prerelease: false
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - "~>"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '1.6'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0.2'
|
63
|
+
name: self_enumerable
|
64
|
+
prerelease: false
|
65
|
+
type: :runtime
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - "~>"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0.2'
|
71
|
+
description:
|
72
|
+
email: r.sprotte@ub.uni-paderborn.de
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- ".rspec"
|
79
|
+
- ".travis.yml"
|
80
|
+
- Gemfile
|
81
|
+
- License.txt
|
82
|
+
- Rakefile
|
83
|
+
- Readme.md
|
84
|
+
- bin/console
|
85
|
+
- lib/metacrunch/mab2.rb
|
86
|
+
- lib/metacrunch/mab2/builder.rb
|
87
|
+
- lib/metacrunch/mab2/cli.rb
|
88
|
+
- lib/metacrunch/mab2/document.rb
|
89
|
+
- lib/metacrunch/mab2/document/controlfield.rb
|
90
|
+
- lib/metacrunch/mab2/document/datafield.rb
|
91
|
+
- lib/metacrunch/mab2/document/datafield_set.rb
|
92
|
+
- lib/metacrunch/mab2/document/jruby/mab_xml_parser.rb
|
93
|
+
- lib/metacrunch/mab2/document/mab_xml_parser.rb
|
94
|
+
- lib/metacrunch/mab2/document/subfield.rb
|
95
|
+
- lib/metacrunch/mab2/document/subfield_set.rb
|
96
|
+
- lib/metacrunch/mab2/version.rb
|
97
|
+
- lib/metacrunch/mab2/xml_builder.rb
|
98
|
+
- metacrunch-mab2.gemspec
|
99
|
+
homepage: http://github.com/ubpb/metacrunch-mab2
|
100
|
+
licenses:
|
101
|
+
- MIT
|
102
|
+
metadata: {}
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
requirements: []
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 2.4.8
|
120
|
+
signing_key:
|
121
|
+
specification_version: 4
|
122
|
+
summary: MAB2 tools for metacrunch
|
123
|
+
test_files: []
|