libis-tools 0.9.6 → 0.9.7
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/lib/libis/tools/config_file.rb +18 -13
- data/lib/libis/tools/metadata/dublin_core_record.rb +95 -0
- data/lib/libis/tools/metadata/field_spec.rb +81 -0
- data/lib/libis/tools/metadata/fix_field.rb +25 -0
- data/lib/libis/tools/metadata/marc21_record.rb +49 -0
- data/lib/libis/tools/metadata/marc_record.rb +209 -0
- data/lib/libis/tools/{sharepoint_mapping.rb → metadata/sharepoint_mapping.rb} +0 -0
- data/lib/libis/tools/{sharepoint_record.rb → metadata/sharepoint_record.rb} +0 -0
- data/lib/libis/tools/metadata/var_field.rb +224 -0
- data/lib/libis/tools/version.rb +1 -1
- data/lib/libis/tools/xml_document.rb +28 -12
- data/lib/libis/tools.rb +2 -0
- data/spec/config_file_spec.rb +39 -0
- data/spec/metadata/dublin_core_spec.rb +81 -0
- data/spec/xmldocument_spec.rb +10 -2
- metadata +12 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e717837dc7e2b3f0549cf1b6abf6ca1240f1344
|
4
|
+
data.tar.gz: 8310be003731268e303dd930279638d61b6a5edf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8fce8638e6fc55803704fda53975fedce79a0ed127c2c8e2cf7dd8b989e6d87af001a56205d1091865764c5fa99dc864dd473dd23df637b24e305f29d49d8df0
|
7
|
+
data.tar.gz: 8b8f8b6b0af625240709d68fd48ea75003c7fe8dbf460cdaecd4d67d6f8a2a19a9aad07daae54ab9602237769ec118807eeb6d92107b34c64d48fcb9af15ad48
|
@@ -34,8 +34,7 @@ module Libis
|
|
34
34
|
#
|
35
35
|
# @param [String,Hash] file_or_hash optional String or Hash argument to initialize the data.
|
36
36
|
def initialize(file_or_hash = nil, opt = {})
|
37
|
-
super(
|
38
|
-
self << file_or_hash
|
37
|
+
super _file_to_hash(file_or_hash), opt
|
39
38
|
end
|
40
39
|
|
41
40
|
# Load configuration parameters from a YAML file or Hash.
|
@@ -48,7 +47,21 @@ module Libis
|
|
48
47
|
#
|
49
48
|
# @param [String,Hash] file_or_hash optional String or Hash argument to initialize the data.
|
50
49
|
def <<(file_or_hash)
|
51
|
-
|
50
|
+
_file_to_hash(file_or_hash).each { |key, value| self[key] = value }
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
# Save configuration parameters in a YAML file.
|
55
|
+
#
|
56
|
+
# @param [String] file path of the YAML file to save the configuration to.
|
57
|
+
def >>(file)
|
58
|
+
File.open(file, 'w') { |f| f.write to_hash.to_yaml }
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def _file_to_hash(file_or_hash)
|
64
|
+
return {} if file_or_hash.nil? || (file_or_hash.respond_to?(:empty?) && file_or_hash.empty?)
|
52
65
|
hash = case file_or_hash
|
53
66
|
when Hash
|
54
67
|
yield file_or_hash if block_given?
|
@@ -61,16 +74,8 @@ module Libis
|
|
61
74
|
else
|
62
75
|
{}
|
63
76
|
end
|
64
|
-
|
65
|
-
hash
|
66
|
-
self
|
67
|
-
end
|
68
|
-
|
69
|
-
# Save configuration parameters in a YAML file.
|
70
|
-
#
|
71
|
-
# @param [String] file path of the YAML file to save the configuration to.
|
72
|
-
def >>(file)
|
73
|
-
File.open(file, 'w') { |f| f.write to_hash.to_yaml }
|
77
|
+
hash = {} unless hash.is_a? Hash
|
78
|
+
hash
|
74
79
|
end
|
75
80
|
|
76
81
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'nori'
|
3
|
+
require 'libis/tools/assert'
|
4
|
+
|
5
|
+
module Libis
|
6
|
+
module Tools
|
7
|
+
module Metadata
|
8
|
+
|
9
|
+
class DublinCoreRecord < Libis::Tools::XmlDocument
|
10
|
+
|
11
|
+
DC_ELEMENTS = %w'contributor coverage creator date description format identifier language' +
|
12
|
+
%w'publisher relation rights source subject title type'
|
13
|
+
DCTERMS_ELEMENTS = %w'abstract accessRights accrualMethod accrualPeriodicity accrualPolicy alternative' +
|
14
|
+
%w'audience available bibliographicCitation conformsTo contributor coverage created creator date' +
|
15
|
+
%w'dateAccepted dateCopyrighted dateSubmitted description educationLevel extent format hasFormat' +
|
16
|
+
%w'hasPart hasVersion identifier instructionalMethod isFormatOf isPartOf isReferencedBy isReplacedBy' +
|
17
|
+
%w'isRequiredBy issued isVersionOf language license mediator medium modified provenance publisher' +
|
18
|
+
%w'references relation replaces requires rights rightsHolder source spatial subject tableOfContents' +
|
19
|
+
%w'temporal title type valid'
|
20
|
+
|
21
|
+
def initialize(doc = nil)
|
22
|
+
super()
|
23
|
+
xml_doc = case doc
|
24
|
+
when ::Libis::Tools::XmlDocument
|
25
|
+
doc
|
26
|
+
when String
|
27
|
+
# noinspection RubyResolve
|
28
|
+
File.exist?(doc) ? Libis::Tools::XmlDocument.load(doc) : Libis::Tools::XmlDocument.parse(doc)
|
29
|
+
when IO
|
30
|
+
Libis::Tools::XmlDocument.parse(doc.read)
|
31
|
+
when Hash
|
32
|
+
Libis::Tools::XmlDocument.from_hash(doc)
|
33
|
+
when NilClass
|
34
|
+
Libis::Tools::XmlDocument.new.build do |xml|
|
35
|
+
xml.record('xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
36
|
+
'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
|
37
|
+
'xmlns:dcterms' => 'http://purl.org/dc/terms/') {
|
38
|
+
yield xml
|
39
|
+
}
|
40
|
+
end
|
41
|
+
else
|
42
|
+
raise ArgumentError, "Invalid argument: #{doc.inspect}"
|
43
|
+
end
|
44
|
+
@document = xml_doc.document if xml_doc
|
45
|
+
end
|
46
|
+
|
47
|
+
def all
|
48
|
+
@all_records ||= get_all_records
|
49
|
+
end
|
50
|
+
|
51
|
+
def xpath(path)
|
52
|
+
m = /^([\/.]*\/)?(dc(terms)?:)?(.*)/.match(path.to_s)
|
53
|
+
return [] unless m[4]
|
54
|
+
path = (m[1] || '') + ('dc:' || m[2]) + m[4]
|
55
|
+
raise ArgumentError, 'XML document not valid.' if self.invalid?
|
56
|
+
@document.xpath(path.to_s)
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_node(name, value = nil, parent = nil, attributes = {})
|
60
|
+
ns, tag = get_namespace(name.to_s)
|
61
|
+
(attributes[:namespaces] ||= {})[:node_ns] ||= ns if ns
|
62
|
+
super tag, value, parent, attributes
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
def get_nodes(tag, parent = nil)
|
68
|
+
parent ||= root
|
69
|
+
m = /^([\/\.]*\/)?(dc(?:terms)?:)?(.*)/.match(tag.to_s)
|
70
|
+
return [] unless m[3]
|
71
|
+
path = (m[1] || '') + ('dc:' || m[2]) + m[3]
|
72
|
+
parent.xpath(path)
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_namespace(tag)
|
76
|
+
m = /^((dc)?(terms)?(?:_|:)?)?([a-zA-Z_][-_.0-9a-zA-Z]+)(.*)/.match tag
|
77
|
+
ns = if m[1].nil?
|
78
|
+
if DC_ELEMENTS.include?(m[4])
|
79
|
+
:dc
|
80
|
+
else
|
81
|
+
DCTERMS_ELEMENTS.include?(m[4]) ? :dcterms : nil
|
82
|
+
end
|
83
|
+
elsif m[3].nil?
|
84
|
+
:dc
|
85
|
+
else
|
86
|
+
:dcterms
|
87
|
+
end
|
88
|
+
[ns, "#{m[4]}#{m[5]}"]
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Libis
|
4
|
+
module Tools
|
5
|
+
module Metadata
|
6
|
+
|
7
|
+
class FieldSpec
|
8
|
+
|
9
|
+
attr_accessor :parts
|
10
|
+
attr_accessor :prefix
|
11
|
+
attr_accessor :join
|
12
|
+
attr_accessor :postfix
|
13
|
+
|
14
|
+
def initialize(*parts)
|
15
|
+
@parts = []
|
16
|
+
self[*parts]
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_options(options = {})
|
20
|
+
if options[:fix]
|
21
|
+
if options[:fix].size == 2
|
22
|
+
@prefix, @postfix = options[:fix].split('')
|
23
|
+
else
|
24
|
+
@prefix, @postfix = options[:fix].split('|')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
@join = options[:join] if options[:join]
|
28
|
+
@prefix = FieldSpec::from(options[:prefix]) if options[:prefix]
|
29
|
+
@postfix = FieldSpec::from(options[:postfix]) if options[:postfix]
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_default_options(options = {})
|
34
|
+
options.delete(:prefix) if @prefix
|
35
|
+
options.delete(:postfix) if @postfix
|
36
|
+
options.delete(:fix) if @prefix or @postfix
|
37
|
+
options.delete(:join) if @join
|
38
|
+
add_options options
|
39
|
+
end
|
40
|
+
|
41
|
+
def [](*parts)
|
42
|
+
options = parts.last.is_a?(Hash) ? parts.pop : {}
|
43
|
+
parts.each { |x| add x }
|
44
|
+
x = options.delete(:parts)
|
45
|
+
add x if x
|
46
|
+
add_options options
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.from(*h)
|
50
|
+
FieldSpec.new(*h)
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
@parts.delete_if { |x|
|
55
|
+
x.nil? or
|
56
|
+
(x.is_a? String and x.empty?) or
|
57
|
+
(x.is_a? FieldSpec and x.to_s.empty?)
|
58
|
+
}
|
59
|
+
result = @parts.join(@join)
|
60
|
+
unless result.empty?
|
61
|
+
result = (@prefix || '').to_s + result + (@postfix || '').to_s
|
62
|
+
end
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
def add(part)
|
67
|
+
case part
|
68
|
+
when Hash
|
69
|
+
@parts << FieldSpec::from(part)
|
70
|
+
when Array
|
71
|
+
part.each { |x| add x }
|
72
|
+
else
|
73
|
+
@parts << part
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Libis
|
4
|
+
module Tools
|
5
|
+
module Metadata
|
6
|
+
|
7
|
+
class FixField
|
8
|
+
|
9
|
+
attr_reader :tag
|
10
|
+
attr_reader :datas
|
11
|
+
|
12
|
+
def initialize(tag, datas)
|
13
|
+
@tag = tag
|
14
|
+
@datas = datas || ''
|
15
|
+
end
|
16
|
+
|
17
|
+
def dump
|
18
|
+
"#{@tag}:'#{@datas}'\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
require_relative 'marc_record'
|
6
|
+
|
7
|
+
module Libis
|
8
|
+
module Tools
|
9
|
+
module Metadata
|
10
|
+
|
11
|
+
class Marc21Record < Libis::Tools::Metadata::MarcRecord
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def get_all_records
|
16
|
+
|
17
|
+
@all_records = Hash.new { |h, k| h[k] = [] }
|
18
|
+
|
19
|
+
@node.xpath('.//leader').each { |f|
|
20
|
+
@all_records['LDR'] << FixField.new('LDR', f.content)
|
21
|
+
}
|
22
|
+
|
23
|
+
@node.xpath('.//controlfield').each { |f|
|
24
|
+
tag = f['tag']
|
25
|
+
tag = '%03d' % tag.to_i if tag.size < 3
|
26
|
+
@all_records[tag] << FixField.new(tag, CGI::escapeHTML(f.content))
|
27
|
+
}
|
28
|
+
|
29
|
+
@node.xpath('.//datafield').each { |v|
|
30
|
+
|
31
|
+
tag = v['tag']
|
32
|
+
tag = '%03d' % tag.to_i if tag.size < 3
|
33
|
+
|
34
|
+
subfields = Hash.new { |h, k| h[k] = [] }
|
35
|
+
v.xpath('.//subfield').each { |s| subfields[s['code']] << CGI::escapeHTML(s.content) }
|
36
|
+
|
37
|
+
@all_records[tag] << VarField.new(tag, v['ind1'].to_s, v['ind2'].to_s, subfields)
|
38
|
+
|
39
|
+
}
|
40
|
+
|
41
|
+
@all_records
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
require 'libis/tools/xml_document'
|
7
|
+
require 'libis/tools/assert'
|
8
|
+
|
9
|
+
require_relative 'fix_field'
|
10
|
+
require_relative 'var_field'
|
11
|
+
require_relative 'field_spec'
|
12
|
+
|
13
|
+
module Libis
|
14
|
+
module Tools
|
15
|
+
module Metadata
|
16
|
+
|
17
|
+
# noinspection RubyTooManyMethodsInspection
|
18
|
+
class MarcRecord
|
19
|
+
|
20
|
+
def initialize(xml_node)
|
21
|
+
@node = xml_node
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_raw
|
25
|
+
@node
|
26
|
+
end
|
27
|
+
|
28
|
+
def all
|
29
|
+
# noinspection RubyResolve
|
30
|
+
@all_records ||= get_all_records
|
31
|
+
end
|
32
|
+
|
33
|
+
def each
|
34
|
+
all.each do |k, v|
|
35
|
+
yield k, v
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def all_tags(tag, subfields = '')
|
40
|
+
tag_, ind1, ind2 = tag =~ /^\d{3}/ ? [tag[0..2], tag[3], tag[4]] : [tag, nil, nil]
|
41
|
+
result = get_records(tag_, ind1, ind2, subfields)
|
42
|
+
return result unless block_given?
|
43
|
+
result.map { |record| yield record }
|
44
|
+
result.size > 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def first_tag(t, subfields = '')
|
48
|
+
result = all_tags(t, subfields).first
|
49
|
+
return result unless block_given?
|
50
|
+
return false unless result
|
51
|
+
yield result
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
def each_tag(t, s = '')
|
56
|
+
all_tags(t, s).each do |record|
|
57
|
+
yield record
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def all_fields(t, s)
|
62
|
+
r = all_tags(t, s).collect { |tag| tag.fields_array(s) }.flatten.compact
|
63
|
+
return r unless block_given?
|
64
|
+
r.map { |field| yield field }
|
65
|
+
r.size > 0
|
66
|
+
end
|
67
|
+
|
68
|
+
def first_field(t, s)
|
69
|
+
result = all_fields(t, s).first
|
70
|
+
return result unless block_given?
|
71
|
+
return false unless result
|
72
|
+
yield result
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def each_field(t, s)
|
78
|
+
all_fields(t, s).each do |field|
|
79
|
+
yield field
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def marc_dump
|
84
|
+
all.values.flatten.each_with_object([]) { |record, m| m << record.dump }.join
|
85
|
+
end
|
86
|
+
|
87
|
+
def save(filename)
|
88
|
+
|
89
|
+
doc = ::Libis::Tools::XmlDocument.new
|
90
|
+
doc.root = @node
|
91
|
+
|
92
|
+
return doc unless filename
|
93
|
+
|
94
|
+
doc.save filename, save_with: (::Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS |
|
95
|
+
::Nokogiri::XML::Node::SaveOptions::AS_XML |
|
96
|
+
::Nokogiri::XML::Node::SaveOptions::FORMAT
|
97
|
+
)
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.load(filename)
|
102
|
+
|
103
|
+
doc = ::Libis::Tools::XmlDocument.open(filename)
|
104
|
+
self.new(doc.root)
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.read(io)
|
109
|
+
io = StringIO.new(io) if io.is_a? String
|
110
|
+
doc = ::Libis::Tools::XmlDocument.parse(io)
|
111
|
+
self.new(doc.root)
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
def to_aseq
|
116
|
+
record = ''
|
117
|
+
doc_number = tag('001').datas
|
118
|
+
|
119
|
+
all.select { |t| t.is_a? FixField }.each { |t| record += "#{format('%09s', doc_number)} #{t.tag} L #{t.datas}\n" }
|
120
|
+
all.select { |t| t.is_a? VarField }.each { |t|
|
121
|
+
record += "#{format('%09s', doc_number)} #{t.tag}#{t.ind1}#{t.ind2} L "
|
122
|
+
t.keys.each { |k|
|
123
|
+
t.field_array(k).each { |f|
|
124
|
+
record += "$$#{k}#{CGI::unescapeHTML(f)}"
|
125
|
+
}
|
126
|
+
}
|
127
|
+
record += "\n"
|
128
|
+
}
|
129
|
+
|
130
|
+
record
|
131
|
+
end
|
132
|
+
|
133
|
+
protected
|
134
|
+
|
135
|
+
def element(*parts)
|
136
|
+
opts = options parts
|
137
|
+
field_spec(opts, *parts)
|
138
|
+
end
|
139
|
+
|
140
|
+
def list_s(*parts)
|
141
|
+
opts = options parts, join: ' '
|
142
|
+
field_spec(opts, *parts)
|
143
|
+
end
|
144
|
+
|
145
|
+
def list_c(*parts)
|
146
|
+
opts = options parts, join: ', '
|
147
|
+
field_spec(opts, *parts)
|
148
|
+
end
|
149
|
+
|
150
|
+
def list_d(*parts)
|
151
|
+
opts = options parts, join: ' - '
|
152
|
+
field_spec(opts, *parts)
|
153
|
+
end
|
154
|
+
|
155
|
+
def repeat(*parts)
|
156
|
+
opts = options parts, join: '; '
|
157
|
+
field_spec(opts, *parts)
|
158
|
+
end
|
159
|
+
|
160
|
+
def opt_r(*parts)
|
161
|
+
opts = options parts, fix: '()'
|
162
|
+
field_spec(opts, *parts)
|
163
|
+
end
|
164
|
+
|
165
|
+
def opt_s(*parts)
|
166
|
+
opts = options parts, fix: '[]'
|
167
|
+
field_spec(opts, *parts)
|
168
|
+
end
|
169
|
+
|
170
|
+
def odis_link(group, id, label)
|
171
|
+
"http://www.odis.be/lnk/#{group.downcase[0, 2]}_#{id}\##{label}"
|
172
|
+
end
|
173
|
+
|
174
|
+
private
|
175
|
+
|
176
|
+
def options(args, default = {})
|
177
|
+
default.merge(args.last.is_a?(::Hash) ? args.pop : {})
|
178
|
+
end
|
179
|
+
|
180
|
+
def field_spec(default_options, *parts)
|
181
|
+
FieldSpec.new(*parts).add_default_options(default_options).to_s
|
182
|
+
end
|
183
|
+
|
184
|
+
def get_records(tag, ind1 = '', ind2 = '', subfields = '')
|
185
|
+
|
186
|
+
ind1 ||= ''
|
187
|
+
ind2 ||= ''
|
188
|
+
subfields ||= ''
|
189
|
+
|
190
|
+
ind1.tr!('_', ' ')
|
191
|
+
ind1.tr!('#', '')
|
192
|
+
|
193
|
+
ind2.tr!('_', ' ')
|
194
|
+
ind2.tr!('#', '')
|
195
|
+
|
196
|
+
all[tag].select do |v|
|
197
|
+
v.is_a?(FixField) ||
|
198
|
+
((ind1.empty? or v.ind1 == ind1) &&
|
199
|
+
(ind2.empty? or v.ind2 == ind2) &&
|
200
|
+
v.match_fieldspec?(subfields)
|
201
|
+
)
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,224 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'libis/tools/assert'
|
4
|
+
|
5
|
+
module Libis
|
6
|
+
module Tools
|
7
|
+
module Metadata
|
8
|
+
|
9
|
+
class VarField
|
10
|
+
|
11
|
+
attr_reader :tag
|
12
|
+
attr_reader :ind1
|
13
|
+
attr_reader :ind2
|
14
|
+
attr_reader :subfield
|
15
|
+
|
16
|
+
def initialize(tag, ind1, ind2, subfield = {})
|
17
|
+
@tag = tag
|
18
|
+
@ind1 = ind1 || ' '
|
19
|
+
@ind2 = ind2 || ' '
|
20
|
+
@subfield = subfield || {}
|
21
|
+
end
|
22
|
+
|
23
|
+
# dump the contents
|
24
|
+
#
|
25
|
+
# @return [String] debug output to inspect the contents of the VarField
|
26
|
+
def dump
|
27
|
+
output = "#{@tag}:#{@ind1}:#{@ind2}:\n"
|
28
|
+
@subfield.each { |s, t| output += "\t#{s}:#{t}\n" }
|
29
|
+
output
|
30
|
+
end
|
31
|
+
|
32
|
+
# dump the contents
|
33
|
+
#
|
34
|
+
# @return [String] debug output to inspect the contents of the VarField - Single line version
|
35
|
+
def dump_line
|
36
|
+
output = "#{@tag}:#{@ind1}:#{@ind2}:"
|
37
|
+
@subfield.each { |s, t| output += "$#{s}#{t}" }
|
38
|
+
output
|
39
|
+
end
|
40
|
+
|
41
|
+
# list the subfield codes
|
42
|
+
#
|
43
|
+
# @return [Array] a list of all subfield codes
|
44
|
+
def keys
|
45
|
+
@subfield.keys
|
46
|
+
end
|
47
|
+
|
48
|
+
# get the first (or only) subfield value for the given code
|
49
|
+
#
|
50
|
+
# @return [String] the first or only entry of a subfield or nil if not present
|
51
|
+
# @param s [Character] the subfield code
|
52
|
+
def field(s)
|
53
|
+
field_array(s).first
|
54
|
+
end
|
55
|
+
|
56
|
+
# get a list of all subfield values for a given code
|
57
|
+
#
|
58
|
+
# @return [Array] all the entries of a repeatable subfield
|
59
|
+
# @param s [Character] the subfield code
|
60
|
+
def field_array(s)
|
61
|
+
assert(s.is_a?(String) && (s =~ /^[\da-z]$/) == 0, 'method expects a lower case alphanumerical char')
|
62
|
+
@subfield.has_key?(s) ? @subfield[s].dup : []
|
63
|
+
end
|
64
|
+
|
65
|
+
# get a list of the first subfield value for all the codes in the given string
|
66
|
+
#
|
67
|
+
# @return [Array] list of the first or only entries of all subfield codes in the input string
|
68
|
+
# @param s [String] subfield code specification (see match_fieldspec?)
|
69
|
+
#
|
70
|
+
# The subfield codes are cleaned and sorted first (see fieldspec_to_sorted_array)
|
71
|
+
def fields(s)
|
72
|
+
assert(s.is_a?(String), 'method expects a string')
|
73
|
+
return [] unless (match_array = match_fieldspec?(s))
|
74
|
+
fieldspec_to_array(match_array.join(' ')).collect { |i| send(:field, i) }.flatten.compact
|
75
|
+
end
|
76
|
+
|
77
|
+
# get a list of all the subfield values for all the codes in the given string
|
78
|
+
#
|
79
|
+
# @return [Array] list of the all the entries of all subfield codes in the input string
|
80
|
+
# @param s [String] subfield code specification (see match_fieldspec?)
|
81
|
+
#
|
82
|
+
# The subfield codes are cleaned and sorted first (see fieldspec_to_sorted_array)
|
83
|
+
|
84
|
+
def fields_array(s)
|
85
|
+
assert(s.is_a?(String), 'method expects a string')
|
86
|
+
return [] unless (match_array = match_fieldspec?(s))
|
87
|
+
fieldspec_to_array(match_array.join(' ')).collect { |i| send(:field_array, i) }.flatten.compact
|
88
|
+
end
|
89
|
+
|
90
|
+
# check if the current VarField matches the given field specification.
|
91
|
+
#
|
92
|
+
# @return [String] The matching part(s) of the specification or nil if no match
|
93
|
+
# @param fieldspec [String] field specification: sequence of alternative set of subfield codes that should-shouldn't be present
|
94
|
+
#
|
95
|
+
# The fieldspec consists of groups of characters. At least one of these groups should match for the test to succeed
|
96
|
+
# Within the group sets of codes may be divided by a hyphen (-). The first set of codes must all be present;
|
97
|
+
# the second set of codes must all <b>not</b> be present. Either set may be empty.
|
98
|
+
#
|
99
|
+
# Examples:
|
100
|
+
# 'ab' matches '$a...$b...' => ['ab']
|
101
|
+
# '$a...$b...$c...' => ['ab']
|
102
|
+
# but not '$a...' => nil # ($b missing)
|
103
|
+
# '$b...' => nil # ($a missing)
|
104
|
+
# 'a b' matches '$a...' => ['a']
|
105
|
+
# '$b...' => ['b']
|
106
|
+
# '$a...$b...' => ['a', 'b']
|
107
|
+
# '$a...$b...$c...' => ['a', 'b']
|
108
|
+
# but not '$c...' => nil # ($a or $b must be present)
|
109
|
+
# 'abc-d' matches '$a..,$b...$c...' => ['abc-d']
|
110
|
+
# '$a..,$b...$c...$e...' => ['abc-d']
|
111
|
+
# but not '$a...$b...$e...' => nil # ($c missing)
|
112
|
+
# '$a...$b...$c...$d...' => nil # ($d should not be present)
|
113
|
+
# 'a-b b-a' matches '$a...' => ['a-b']
|
114
|
+
# '$a...$c...' => ['a-b']
|
115
|
+
# '$b...' => ['b-a']
|
116
|
+
# '$b...$c...' => ['b-a']
|
117
|
+
# but not '$a...$b...' => nil
|
118
|
+
# 'a-b c-d' matches '$a...' => ['a-b']
|
119
|
+
# '$a...$c...' => ['a-b', 'c-d']
|
120
|
+
# '$a...$b...$c...' => ['c-d']
|
121
|
+
# '$b...$c...' => ['c-d']
|
122
|
+
# but not '$a...$b...' => nil
|
123
|
+
# '$c...$d...' => nil
|
124
|
+
# '$b...$c...$d...' => nil
|
125
|
+
# '$a...$b...$c...$d...' => nil
|
126
|
+
def match_fieldspec?(fieldspec)
|
127
|
+
return [] if fieldspec.empty?
|
128
|
+
result = fieldspec.split.collect { |fs|
|
129
|
+
fa = fs.split '-'
|
130
|
+
assert(fa.size <= 2, 'more than one "-" is not allowed in a fieldspec')
|
131
|
+
must_match = (fa[0] || '').split ''
|
132
|
+
must_not_match = (fa[1] || '').split ''
|
133
|
+
next unless (must_match == (must_match & keys)) && (must_not_match & keys).empty?
|
134
|
+
fs
|
135
|
+
}.compact
|
136
|
+
return nil if result.empty?
|
137
|
+
result
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
# @return [Array] cleaned up version of the input string
|
143
|
+
# @param fieldspec [String] subfield code specification
|
144
|
+
# cleans the subfield code specification and splits it into an array of characters
|
145
|
+
# Duplicates will be removed from the array and the order will be untouched.
|
146
|
+
def fieldspec_to_array(fieldspec)
|
147
|
+
|
148
|
+
# note that we remove the '-xxx' part as it is only required for matching
|
149
|
+
fieldspec.gsub(/ |-\w*/, '').split('').uniq
|
150
|
+
end
|
151
|
+
|
152
|
+
def sort_helper(x)
|
153
|
+
# make sure that everything below 'A' is higher than 'z'
|
154
|
+
# note that this only works for numbers, but that is fine in our case.
|
155
|
+
x < 'A' ? (x.to_i + 123).chr : x
|
156
|
+
end
|
157
|
+
|
158
|
+
# implementation for methods for retrieving subfield values
|
159
|
+
#
|
160
|
+
# The methods start with a single character: the operation
|
161
|
+
# 'f' for retrieving only the first occurence of the subfield
|
162
|
+
# 'a' for retrieving all the subfield values for each of the given subfields
|
163
|
+
# if omitted, 'f' is assumed
|
164
|
+
#
|
165
|
+
# Then a '_' acts as a subdivider between the operation and the subfield(s). It must always be present, even
|
166
|
+
# if the operation is omitted.
|
167
|
+
#
|
168
|
+
# The last past is a sequence of subfield codes that should be used for selecting the values. The order in which the
|
169
|
+
# subfields are listed is respected in the resulting array of values.
|
170
|
+
#
|
171
|
+
# Examples:
|
172
|
+
#
|
173
|
+
# t = VarField.new('100', '', '',
|
174
|
+
# { 'a' => %w'Name NickName',
|
175
|
+
# 'b' => %w'LastName MaidenName',
|
176
|
+
# 'c' => %w'eMail',
|
177
|
+
# '1' => %w'Age',
|
178
|
+
# '9' => %w'Score'})
|
179
|
+
#
|
180
|
+
# # >> 100##$aName$aNickName$bLastName$bMaidenName$ceMail$1Age$9Score <<
|
181
|
+
#
|
182
|
+
# t._1ab => ['Age', 'Name', 'LastName']
|
183
|
+
# # equivalent to: t.f_1av or t.fields('1ab')
|
184
|
+
#
|
185
|
+
# t.a_9ab => ['Score', 'Name', 'NickName', 'LastName', 'MaidenName']
|
186
|
+
# # equivalent to: t.fields_array('9ab')
|
187
|
+
#
|
188
|
+
# Note that it is not possible to use a fieldspec for the sequence of subfield codes. Spaces and '-' are not allowed
|
189
|
+
# in method calls. If you want this, use the #field(s) and #field(s)_array methods.
|
190
|
+
#
|
191
|
+
def method_missing(name, *args)
|
192
|
+
operation, subfields = name.to_s.split('_')
|
193
|
+
assert(subfields.size > 0, 'need to specify at least one subfield')
|
194
|
+
operation = 'f' if operation.empty?
|
195
|
+
# convert subfield list to fieldspec
|
196
|
+
subfields = subfields.split('').join(' ')
|
197
|
+
case operation
|
198
|
+
when 'f'
|
199
|
+
if subfields.size > 1
|
200
|
+
operation = :fields
|
201
|
+
else
|
202
|
+
operation = :field
|
203
|
+
end
|
204
|
+
when 'a'
|
205
|
+
if subfields.size > 1
|
206
|
+
operation = :fields_array
|
207
|
+
else
|
208
|
+
operation = :field_array
|
209
|
+
end
|
210
|
+
else
|
211
|
+
throw "Unknown method invocation: '#{name}' with: #{args}"
|
212
|
+
end
|
213
|
+
send(operation, subfields)
|
214
|
+
end
|
215
|
+
|
216
|
+
def to_ary
|
217
|
+
nil
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
data/lib/libis/tools/version.rb
CHANGED
@@ -280,13 +280,19 @@ module Libis
|
|
280
280
|
# </jkr:books>
|
281
281
|
# </patron>
|
282
282
|
#
|
283
|
-
# @param [
|
284
|
-
#
|
285
|
-
#
|
286
|
-
#
|
287
|
-
#
|
283
|
+
# @param [Array] args arguments being:
|
284
|
+
# - tag for the new node
|
285
|
+
# - optional content for new node; empty if nil or not present
|
286
|
+
# - optional parent node for new node; root if nil or not present; xml document if root is not defined
|
287
|
+
# - a Hash containing tag-value pairs for each attribute; the special key ':namespaces'
|
288
|
+
# contains a Hash of namespace definitions as in {#add_namespaces}
|
288
289
|
# @return [Nokogiri::XML::Node] the new node
|
289
|
-
def add_node(
|
290
|
+
def add_node(*args)
|
291
|
+
attributes = {}
|
292
|
+
attributes = args.pop if args.last.is_a? Hash
|
293
|
+
name, value, parent = *args
|
294
|
+
|
295
|
+
return nil if name.nil?
|
290
296
|
|
291
297
|
node = Nokogiri::XML::Node.new name.to_s, @document
|
292
298
|
node.content = value
|
@@ -386,7 +392,7 @@ module Libis
|
|
386
392
|
end
|
387
393
|
|
388
394
|
node.namespace_scopes.each do |ns|
|
389
|
-
node.namespace = ns if ns.prefix == node_ns
|
395
|
+
node.namespace = ns if ns.prefix == node_ns.to_s
|
390
396
|
end if node_ns
|
391
397
|
|
392
398
|
node.default_namespace = default_ns if default_ns
|
@@ -430,12 +436,24 @@ module Libis
|
|
430
436
|
# xml_doc.value('//email') # => "harry.potter@hogwarts.edu"
|
431
437
|
#
|
432
438
|
# @param [String] path the name or XPath term to search the node(s)
|
439
|
+
# @param [Node] parent parent node; document if nil
|
433
440
|
# @return [String] content or nil if not found
|
434
|
-
def value(path)
|
435
|
-
|
441
|
+
def value(path, parent = nil)
|
442
|
+
parent ||= document
|
443
|
+
parent.xpath(path).first.content rescue nil
|
436
444
|
end
|
437
445
|
|
438
|
-
|
446
|
+
# Return the content of the first element found.
|
447
|
+
#
|
448
|
+
# Example:
|
449
|
+
#
|
450
|
+
# xml_doc['email'] # => "harry.potter@hogwarts.edu"
|
451
|
+
#
|
452
|
+
# @param [String] path the name or XPath term to search the node(s)
|
453
|
+
# @return [String] content or nil if not found
|
454
|
+
def [](path)
|
455
|
+
xpath(path).first.content rescue nil
|
456
|
+
end
|
439
457
|
|
440
458
|
# Return the content of all elements found.
|
441
459
|
# Example:
|
@@ -548,8 +566,6 @@ module Libis
|
|
548
566
|
node
|
549
567
|
end
|
550
568
|
|
551
|
-
protected
|
552
|
-
|
553
569
|
# Get the first node matching the tag. The node will be seached with XPath search term = "//#{tag}".
|
554
570
|
#
|
555
571
|
# @param [String] tag XML tag to look for; XPath syntax is allowed
|
data/lib/libis/tools.rb
CHANGED
@@ -4,7 +4,9 @@ module Libis
|
|
4
4
|
autoload :Checksum, 'libis/tools/checksum'
|
5
5
|
autoload :Command, 'libis/tools/command'
|
6
6
|
autoload :Config, 'libis/tools/config'
|
7
|
+
autoload :ConfigFile, 'libis/tools/config_file'
|
7
8
|
autoload :DCRecord, 'libis/tools/dc_record'
|
9
|
+
autoload :DeepStruct, 'libis/tools/deep_struct'
|
8
10
|
autoload :Logger, 'libis/tools/logger'
|
9
11
|
autoload :MetsFile, 'libis/tools/mets_file'
|
10
12
|
autoload :Parameter, 'libis/tools/parameter'
|
data/spec/config_file_spec.rb
CHANGED
@@ -30,6 +30,45 @@ describe ::Libis::Tools::ConfigFile do
|
|
30
30
|
expect(subject.to_hash).to eq hash
|
31
31
|
end
|
32
32
|
|
33
|
+
it 'loads a hash' do
|
34
|
+
subject << hash
|
35
|
+
expect(subject.to_hash).to eq hash
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'allows to change sub-hash' do
|
39
|
+
subject << hash
|
40
|
+
# noinspection RubyResolve
|
41
|
+
subject.b.v = 1
|
42
|
+
hash[:b]['v'] = 1
|
43
|
+
expect(subject.to_hash).to eq hash
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'allows to change hash in array' do
|
47
|
+
subject << hash
|
48
|
+
# noinspection RubyResolve
|
49
|
+
subject.c[0][0].a[0].v = 1
|
50
|
+
hash[:c][0][0][:a][0]['v'] = 1
|
51
|
+
expect(subject.to_hash).to eq hash
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'initialization with hash' do
|
57
|
+
subject { ::Libis::Tools::ConfigFile.new hash }
|
58
|
+
|
59
|
+
it 'has hash' do
|
60
|
+
expect(subject.to_hash).to eq hash
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'initialization with file' do
|
66
|
+
subject { ::Libis::Tools::ConfigFile.new test_file }
|
67
|
+
|
68
|
+
it 'has hash' do
|
69
|
+
expect(subject.to_hash).to eq hash
|
70
|
+
end
|
71
|
+
|
33
72
|
end
|
34
73
|
|
35
74
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require_relative '../spec_helper'
|
3
|
+
require 'libis/tools/metadata/dublin_core_record'
|
4
|
+
|
5
|
+
require 'rspec/matchers'
|
6
|
+
require 'equivalent-xml'
|
7
|
+
|
8
|
+
describe 'DublinCoreRecord' do
|
9
|
+
|
10
|
+
let(:header) { '<?xml version="1.0" encoding="utf-8"?>' }
|
11
|
+
|
12
|
+
subject(:dc) { Libis::Tools::Metadata::DublinCoreRecord.new(data) {} }
|
13
|
+
|
14
|
+
def dc_xml(tag, value = '', attributes = {})
|
15
|
+
"<dc:#{tag}#{attributes.sort.each{|k,v| " #{k}=\"#{v}\""}.join}>#{value}</dc:#{tag}>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def dcterms_xml(tag, value = '', attributes = {})
|
19
|
+
"<dcterms:#{tag}#{attributes.sort.each{|k,v| " #{k}=\"#{v}\""}.join}>#{value}</dcterms:#{tag}>"
|
20
|
+
end
|
21
|
+
|
22
|
+
def match_xml(doc1, doc2)
|
23
|
+
xml1 = doc1.is_a?(::Libis::Tools::XmlDocument) ? doc1.document : ::Nokogiri::XML(doc1.to_s)
|
24
|
+
xml2 = doc2.is_a?(::Libis::Tools::XmlDocument) ? doc2.document : ::Nokogiri::XML(doc2.to_s)
|
25
|
+
# noinspection RubyResolve
|
26
|
+
expect(xml1).to be_equivalent_to(xml2).respecting_element_order
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'Empty record' do
|
30
|
+
let(:data) { nil }
|
31
|
+
let(:root) { <<STR.chomp
|
32
|
+
<record \
|
33
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
|
34
|
+
xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/"
|
35
|
+
STR
|
36
|
+
}
|
37
|
+
let(:record_start) { root + '>' }
|
38
|
+
let(:record_end) { '</record>' }
|
39
|
+
let(:empty_record) { header + root + '/>' }
|
40
|
+
|
41
|
+
|
42
|
+
it 'contains emtpy record' do
|
43
|
+
match_xml dc.document, empty_record
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'add dc:title' do
|
47
|
+
dc.title = 'abc'
|
48
|
+
match_xml dc.document, header + record_start + dc_xml('title', 'abc') + record_end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'add dc:date' do
|
52
|
+
dc.date = '2001'
|
53
|
+
dc.dcdate = '2002'
|
54
|
+
dc.dc_date = '2003'
|
55
|
+
match_xml dc.document,
|
56
|
+
header +
|
57
|
+
record_start +
|
58
|
+
dc_xml('date', '2001') +
|
59
|
+
dc_xml('date', '2002') +
|
60
|
+
dc_xml('date', '2003') +
|
61
|
+
record_end
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'add dcterms:date' do
|
65
|
+
dc.termsdate = '2001'
|
66
|
+
dc.dctermsdate = '2002'
|
67
|
+
dc.terms_date = '2003'
|
68
|
+
dc.dcterms_date = '2004'
|
69
|
+
match_xml dc.document,
|
70
|
+
header +
|
71
|
+
record_start +
|
72
|
+
dcterms_xml('date', '2001') +
|
73
|
+
dcterms_xml('date', '2002') +
|
74
|
+
dcterms_xml('date', '2003') +
|
75
|
+
dcterms_xml('date', '2004') +
|
76
|
+
record_end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
data/spec/xmldocument_spec.rb
CHANGED
@@ -199,7 +199,7 @@ describe 'XML Document' do
|
|
199
199
|
|
200
200
|
xml_doc.add_node :patron
|
201
201
|
xml_doc.add_node :name, 'Harry Potter'
|
202
|
-
books = xml_doc.add_node :books,
|
202
|
+
books = xml_doc.add_node :books, namespaces: { jkr: 'http://JKRowling.com' , node_ns: 'jkr' }
|
203
203
|
xml_doc.add_node :book, nil, books,
|
204
204
|
title: 'Quidditch Through the Ages', author: 'Kennilworthy Whisp', due_date: '1992-4-23',
|
205
205
|
namespaces: {node_ns: 'jkr'}
|
@@ -362,7 +362,7 @@ describe 'XML Document' do
|
|
362
362
|
|
363
363
|
end
|
364
364
|
|
365
|
-
it '
|
365
|
+
it 'allows to parse xml string, save and reload' do
|
366
366
|
xml_doc = ::Libis::Tools::XmlDocument.parse(<<-END.align_left)
|
367
367
|
<patron>
|
368
368
|
<name>Harry Potter</name>
|
@@ -381,6 +381,10 @@ describe 'XML Document' do
|
|
381
381
|
|
382
382
|
match_xml xml_doc.document, @xml_template
|
383
383
|
|
384
|
+
end
|
385
|
+
|
386
|
+
it 'supports build to create XML document' do
|
387
|
+
|
384
388
|
xml_doc = ::Libis::Tools::XmlDocument.build do
|
385
389
|
# noinspection RubyResolve
|
386
390
|
patron {
|
@@ -394,6 +398,10 @@ describe 'XML Document' do
|
|
394
398
|
|
395
399
|
match_xml xml_doc.document, @xml_template
|
396
400
|
|
401
|
+
end
|
402
|
+
|
403
|
+
it 'supports different ways to create nodes' do
|
404
|
+
|
397
405
|
xml_doc = ::Libis::Tools::XmlDocument.new
|
398
406
|
xml_doc.add_node :patron
|
399
407
|
xml_doc.name = 'Harry Potter'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libis-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kris Dekeyser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -194,10 +194,16 @@ files:
|
|
194
194
|
- lib/libis/tools/extend/string.rb
|
195
195
|
- lib/libis/tools/extend/struct.rb
|
196
196
|
- lib/libis/tools/logger.rb
|
197
|
+
- lib/libis/tools/metadata/dublin_core_record.rb
|
198
|
+
- lib/libis/tools/metadata/field_spec.rb
|
199
|
+
- lib/libis/tools/metadata/fix_field.rb
|
200
|
+
- lib/libis/tools/metadata/marc21_record.rb
|
201
|
+
- lib/libis/tools/metadata/marc_record.rb
|
202
|
+
- lib/libis/tools/metadata/sharepoint_mapping.rb
|
203
|
+
- lib/libis/tools/metadata/sharepoint_record.rb
|
204
|
+
- lib/libis/tools/metadata/var_field.rb
|
197
205
|
- lib/libis/tools/mets_file.rb
|
198
206
|
- lib/libis/tools/parameter.rb
|
199
|
-
- lib/libis/tools/sharepoint_mapping.rb
|
200
|
-
- lib/libis/tools/sharepoint_record.rb
|
201
207
|
- lib/libis/tools/version.rb
|
202
208
|
- lib/libis/tools/xml_document.rb
|
203
209
|
- libis-tools.gemspec
|
@@ -212,6 +218,7 @@ files:
|
|
212
218
|
- spec/data/test_config.yml
|
213
219
|
- spec/deep_struct_spec.rb
|
214
220
|
- spec/logger_spec.rb
|
221
|
+
- spec/metadata/dublin_core_spec.rb
|
215
222
|
- spec/parameter_container_spec.rb
|
216
223
|
- spec/parameter_spec.rb
|
217
224
|
- spec/spec_helper.rb
|
@@ -256,6 +263,7 @@ test_files:
|
|
256
263
|
- spec/data/test_config.yml
|
257
264
|
- spec/deep_struct_spec.rb
|
258
265
|
- spec/logger_spec.rb
|
266
|
+
- spec/metadata/dublin_core_spec.rb
|
259
267
|
- spec/parameter_container_spec.rb
|
260
268
|
- spec/parameter_spec.rb
|
261
269
|
- spec/spec_helper.rb
|