relaton-cli 0.1.7 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b73f1ac92117d1c3426a66fbe8ece05535b4441696a62a84f9aa5ce93379900f
4
- data.tar.gz: fb5ceb3383573256860f22af4eea6a2699b7a04e5d014b4764d1d9b4964674d6
3
+ metadata.gz: 602dc6b5405f7e9ad64b82a2db8d7c01e1f3de2aa95324a48cb1bef1f5d83394
4
+ data.tar.gz: 3d59d3c875327a1444f6d95be1d83f9b44e1edb78a40c3e3d1ae62096611f2b3
5
5
  SHA512:
6
- metadata.gz: f3274a54be270c3e9bd72aac19590a78a783015a0b1963b16cea1de3bc7f03924e11399c10324506119f384bdb5ea78392074b43c1666f832ec4eb58bd273b32
7
- data.tar.gz: 99351248582ea4313b872ddcb59ead76c41f6fc4fd1dabde7666b9dae14516d889f734d81d08bf8ceb562dd87fcedb34570c3f18255ee316b35ee6d326650c1d
6
+ metadata.gz: e0b7c3d7b95e26db2bb8392860e2ccaef744caa588885c285cb2ab472ecadda6d08d1393dd0f093f33d918f705351a1092f8b869940a8ee8aa50267446886849
7
+ data.tar.gz: 7c91b43960fbd34ee9500524fad1b355f3681960c623dd1af95f637736f577d516107330de97c4b97bf7785fc50b747c198c7f67ca4003fce8309760aa6a207a
data/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ ## 0.1.8 (2019-02-23)
2
+
3
+ Features:
4
+ - Add the `relaton split` interface
5
+ - Add support to convert single xml file
6
+ - Minor cleanup on bibdata and bibcollection
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "relaton/cli"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require "pry"
11
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/docs/README.adoc CHANGED
@@ -30,6 +30,16 @@ file), a link to that file is inserted.
30
30
  If the `TITLE` or `ORGANIZATION` options are given, they are added to the `Collection-File` output as the
31
31
  title and author of the `relaton-collection` document.
32
32
 
33
+ === relaton split
34
+
35
+ [source,console]
36
+ ----
37
+ $ relaton split Collection-File Relaton-File-Directory -x rxl
38
+ ----
39
+
40
+ Splits a `Relaton-Collection-File` into multiple files in the `Relaton-File-Directory`, and it also
41
+ suports an addional `extension` options to use different extension.
42
+
33
43
  === relaton fetch
34
44
 
35
45
  [source,console]
@@ -1,6 +1,9 @@
1
+ require "relaton/element_finder"
1
2
 
2
3
  module Relaton
3
4
  class Bibcollection
5
+ extend Relaton::ElementFinder
6
+
4
7
  ATTRIBS = %i[
5
8
  title
6
9
  items
@@ -10,13 +13,6 @@ module Relaton
10
13
 
11
14
  attr_accessor *ATTRIBS
12
15
 
13
- def self.ns(xpath)
14
- xpath.gsub(%r{/([a-zA-z])}, "/xmlns:\\1").
15
- gsub(%r{::([a-zA-z])}, "::xmlns:\\1").
16
- gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]* ?=)}, "[xmlns:\\1").
17
- gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]*\])}, "[xmlns:\\1")
18
- end
19
-
20
16
  def initialize(options)
21
17
  self.items = []
22
18
  ATTRIBS.each do |k|
@@ -40,14 +36,16 @@ module Relaton
40
36
  end
41
37
 
42
38
  def self.from_xml(source)
43
- title = source&.at(ns("./relaton-collection/title"))&.text
44
- author = source&.at(ns("./relaton-collection/contributor[role/@type = 'author']/organization/name"))&.text
45
- items = source&.xpath(ns("./relaton-collection/relation"))&.map do |item|
46
- klass = item.at(ns("./bibdata")) ? Bibdata : Bibcollection
47
- klass.from_xml(item.at(ns("./bibdata")) || item)
39
+ title = find_text("./relaton-collection/title", source)
40
+ author = find_text("./relaton-collection/contributor[role/@type = 'author']/organization/name", source)
41
+
42
+ items = find_xpath("./relaton-collection/relation", source)&.map do |item|
43
+ bibdata = find("./bibdata", item)
44
+ klass = bibdata ? Bibdata : Bibcollection
45
+ klass.from_xml(bibdata || item)
48
46
  end
49
- opts = { title: title, author: author, items: items }
50
- new(opts)
47
+
48
+ new(title: title, author: author, items: items)
51
49
  end
52
50
 
53
51
  def new_bib_item_class(options)
@@ -31,13 +31,6 @@ module Relaton
31
31
 
32
32
  attr_accessor *ATTRIBS
33
33
 
34
- def self.ns(xpath)
35
- xpath.gsub(%r{/([a-zA-z])}, "/xmlns:\\1").
36
- gsub(%r{::([a-zA-z])}, "::xmlns:\\1").
37
- gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]* ?=)}, "[xmlns:\\1").
38
- gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]*\])}, "[xmlns:\\1")
39
- end
40
-
41
34
  def initialize(options)
42
35
  options.each_pair do |k,v|
43
36
  send("#{k.to_s}=", v)
@@ -61,55 +54,7 @@ module Relaton
61
54
  end
62
55
 
63
56
  def self.from_xml(source)
64
-
65
- datetype = "circulated"
66
-
67
- # bib.relaton_xml_path = URI.escape("#{relaton_root}/#{id_code}.xml")
68
- revdate = source.at(ns("./date[@type = 'published']")) ||
69
- source.at(ns("./date[@type = 'circulated']")) ||
70
- source.at(ns("./date"))
71
- revdate_value = revdate&.at(ns("./on")) || revdate&.at(ns("./from"))
72
-
73
- if revdate && revdate_value
74
- datetype = revdate["type"]
75
- revdate = begin
76
- Date.parse(revdate_value.text.strip).to_s
77
- rescue
78
- warn "[relaton] parsing published date '#{revdate.text}' failed."
79
- revdate_value.text.strip
80
- end || nil
81
- else
82
- revdate = nil
83
- end
84
-
85
-
86
- options = {
87
- uri: source.at(ns("./uri[not(@type)]"))&.text,
88
- xml: source.at(ns("./uri[@type='xml']"))&.text,
89
- pdf: source.at(ns("./uri[@type='pdf']"))&.text,
90
- html: source.at(ns("./uri[@type='html']"))&.text,
91
- rxl: source.at(ns("./uri[@type='rxl']"))&.text,
92
- doc: source.at(ns("./uri[@type='doc']"))&.text,
93
- docidentifier: source.at(ns("./docidentifier"))&.text,
94
- title: source.at(ns("./title"))&.text,
95
- doctype: source.at(ns("./@type"))&.text,
96
- stage: source.at(ns("./status"))&.text,
97
- technical_committee: source.at(ns("./editorialgroup/technical-committee"))&.text,
98
- abstract: source.at(ns("./abstract"))&.text,
99
- revdate: revdate,
100
- language: source.at(ns("./language"))&.text,
101
- script: source.at(ns("./script"))&.text,
102
- edition: source.at(ns("./edition"))&.text,
103
- copyright_from: source.at(ns("./copyright/from"))&.text,
104
- copyright_owner: source.at(ns("./copyright/owner/organization/name"))&.text,
105
- contributor_author_role: source.at(ns("./contributor/role[@type='author']"))&.text,
106
- contributor_author_organization: source.at(ns("./contributor/role[@type='author']"))&.parent&.at(ns("./organization/name"))&.text,
107
- contributor_publisher_role: source.at(ns("./contributor/role[@type='publisher']"))&.text,
108
- contributor_publisher_organization: source.at(ns("./contributor/role[@type='publisher']"))&.parent&.at(ns("./organization/name"))&.text,
109
- datetype: datetype
110
- }
111
-
112
- new(options)
57
+ new(Relaton::XmlDocument.parse(source))
113
58
  end
114
59
 
115
60
  def to_xml
@@ -173,6 +118,5 @@ module Relaton
173
118
  def to_yaml
174
119
  to_h.to_yaml
175
120
  end
176
-
177
121
  end
178
122
  end
data/lib/relaton/cli.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "thor"
2
2
  require "relaton"
3
+ require "relaton/xml_document"
3
4
  require_relative "cli/command"
4
5
 
5
6
  module Relaton
@@ -11,6 +11,7 @@ module Relaton
11
11
  @options = options
12
12
  @outdir = options.fetch(:outdir, nil)
13
13
  @writable = options.fetch(:write, true)
14
+ @overwrite = options.fetch(:overwrite, true)
14
15
 
15
16
  install_dependencies(options[:require] || [])
16
17
  end
@@ -41,7 +42,7 @@ module Relaton
41
42
 
42
43
  private
43
44
 
44
- attr_reader :file, :outdir, :options, :writable
45
+ attr_reader :file, :outdir, :options, :writable, :overwrite
45
46
 
46
47
  def default_ext
47
48
  raise "Override this method"
@@ -71,7 +72,10 @@ module Relaton
71
72
 
72
73
  def write_to_a_file(content, outfile = nil)
73
74
  outfile ||= Pathname.new(file).sub_ext(extension).to_s
74
- File.open(outfile, "w:utf-8") { |file| file.write(content) }
75
+
76
+ if !File.exists?(outfile) || overwrite
77
+ File.open(outfile, "w:utf-8") { |file| file.write(content) }
78
+ end
75
79
  end
76
80
 
77
81
  def write_to_file_collection(content, format)
@@ -31,21 +31,30 @@ module Relaton
31
31
  Relaton::Cli::RelatonFile.concatenate(source_dir, outfile, options)
32
32
  end
33
33
 
34
+ desc "split Relaton-Collection-File Relaton-XML-Directory", "Split a Relaton Collection into multiple files"
35
+ option :extension, aliases: :x, desc: "File extension of Relaton XML files, defaults to 'rxl'"
36
+
37
+ def split(source, outdir)
38
+ Relaton::Cli::RelatonFile.split(source, outdir, options)
39
+ end
40
+
34
41
  desc "yaml2xml YAML", "Convert Relaton YAML into Relaton Collection XML or separate files"
35
42
  option :extension, aliases: :x, desc: "File extension of Relaton XML files, defaults to 'rxl'"
36
43
  option :prefix, aliases: :p, desc: "Filename prefix of individual Relaton XML files, defaults to empty"
37
44
  option :outdir, aliases: :o, desc: "Output to the specified directory with individual Relaton Bibdata XML files"
38
45
  option :require, aliases: :r, type: :array, desc: "Require LIBRARY prior to execution"
46
+ option :overwrite, aliases: :f, type: :boolean, default: false, desc: "Overwrite the existing file"
39
47
 
40
48
  def yaml2xml(filename)
41
49
  Relaton::Cli::YAMLConvertor.to_xml(filename, options)
42
50
  end
43
51
 
44
- desc "xml2yaml XML", "Convert Relaton YAML into Relaton Bibcollection YAML (and separate files)"
52
+ desc "xml2yaml XML", "Convert Relaton XML into Relaton Bibdata / Bibcollection YAML (and separate files)"
45
53
  option :extension, aliases: :x, desc: "File extension of Relaton YAML files, defaults to 'yaml'"
46
54
  option :prefix, aliases: :p, desc: "Filename prefix of Relaton XML files, defaults to empty"
47
55
  option :outdir, aliases: :o, desc: "Output to the specified directory with individual Relaton Bibdata YAML files"
48
56
  option :require, aliases: :r, type: :array, desc: "Require LIBRARY prior to execution"
57
+ option :overwrite, aliases: :f, type: :boolean, default: false, desc: "Overwrite the existing file"
49
58
 
50
59
  def xml2yaml(filename)
51
60
  Relaton::Cli::XMLConvertor.to_yaml(filename, options)
@@ -54,6 +63,7 @@ module Relaton
54
63
  desc "xml2html RELATON-INDEX-XML", "Convert Relaton Collection XML into HTML"
55
64
  option :stylesheet, aliases: :s, desc: "Stylesheet file path for rendering HTML index"
56
65
  option :templatedir, aliases: :t, desc: "Liquid template directory for rendering Relaton items and collection"
66
+ option :overwrite, aliases: :f, type: :boolean, default: false, desc: "Overwrite the existing file"
57
67
 
58
68
  def xml2html(file, style = nil, template = nil)
59
69
  Relaton::Cli::XMLConvertor.to_html(file, style, template)
@@ -62,6 +72,7 @@ module Relaton
62
72
  desc "yaml2html RELATON-INDEX-YAML", "Concatenate Relaton Collection YAML into HTML"
63
73
  option :stylesheet, aliases: :s, desc: "Stylesheet file path for rendering HTML index"
64
74
  option :templatedir, aliases: :t, desc: "Liquid template directory for rendering Relaton items and collection"
75
+ option :overwrite, aliases: :f, type: :boolean, default: false, desc: "Overwrite the existing file"
65
76
 
66
77
  def yaml2html(file, style = nil, template = nil)
67
78
  Relaton::Cli::YAMLConvertor.to_html(file, style, template)
@@ -19,6 +19,10 @@ module Relaton
19
19
  write_to_file(bibcollection.to_xml)
20
20
  end
21
21
 
22
+ def split
23
+ split_and_write_to_files
24
+ end
25
+
22
26
  # Extract files
23
27
  #
24
28
  # This interface expect us to provide a source file / directory,
@@ -37,7 +41,7 @@ module Relaton
37
41
 
38
42
  # Concatenate files
39
43
  #
40
- ## This interface expect us to provide a source directory, output
44
+ # This interface expect us to provide a source directory, output
41
45
  # file and custom configuration options. Normally, this expect the
42
46
  # source directory to contain RXL fles, but it also converts any
43
47
  # YAML files to RXL and then finally combines those together.
@@ -54,6 +58,24 @@ module Relaton
54
58
  new(source, options.merge(outfile: outfile)).concatenate
55
59
  end
56
60
 
61
+ # Split collection
62
+ #
63
+ # This interface expects us to provide a Relaton Collection
64
+ # file and also an output directory, then it will split that
65
+ # collection into multiple files.
66
+ #
67
+ # By default it usages `rxl` extension for these new files,
68
+ # but we can also customize that by providing the correct
69
+ # one as `extension` option parameter.
70
+ #
71
+ # @param source [File] The source collection file
72
+ # @param output [Dir] The output directory for files
73
+ # @param options [Hash] Options as hash key value pair
74
+ #
75
+ def self.split(source, outdir = nil, options = {})
76
+ new(source, options.merge(outdir: outdir)).split
77
+ end
78
+
57
79
  private
58
80
 
59
81
  attr_reader :source, :options, :outdir, :outfile
@@ -80,6 +102,11 @@ module Relaton
80
102
  end
81
103
  end
82
104
 
105
+ def relaton_collection
106
+ @relaton_collection ||=
107
+ Relaton::Bibcollection.from_xml(nokogiri_document(nil, source))
108
+ end
109
+
83
110
  def extract_and_write_to_files
84
111
  select_source_files.each do |file|
85
112
  xml = nokogiri_document(nil, file)
@@ -94,8 +121,7 @@ module Relaton
94
121
  bibdata = Relaton::Bibdata.from_xml(bib.root)
95
122
  build_bibdata_relaton(bibdata, file)
96
123
 
97
- outfile = [outdir, build_filename(file, bib)].join("/")
98
- write_to_file(bibdata.to_xml, outfile)
124
+ write_to_file(bibdata.to_xml, outdir, build_filename(file))
99
125
  end
100
126
  end
101
127
 
@@ -108,6 +134,16 @@ module Relaton
108
134
  end.compact
109
135
  end
110
136
 
137
+ def split_and_write_to_files
138
+ output_dir = outdir || build_dirname(source)
139
+ write_to_collection_file(relaton_collection.to_yaml, output_dir)
140
+
141
+ relaton_collection.items.each do |content|
142
+ name = build_filename(nil, content.docidentifier)
143
+ write_to_file(content.to_xml, output_dir, name)
144
+ end
145
+ end
146
+
111
147
  def bibdata_instance(document, file)
112
148
  document = clean_nokogiri_document(document)
113
149
  bibdata = Relaton::Bibdata.from_xml(document.root)
@@ -151,15 +187,31 @@ module Relaton
151
187
  Dir[files].reject { |file| File.directory?(file) }
152
188
  end
153
189
 
154
- def write_to_file(content, output_file = nil)
155
- output_file ||= outfile
156
- File.open(output_file, "w:utf-8") { |file| file.write(content) }
190
+ def write_to_file(content, directory = nil, output_file = nil)
191
+ file_with_dir = [directory, output_file || outfile].compact.join("/")
192
+ File.open(file_with_dir, "w:utf-8") { |file| file.write(content) }
193
+ end
194
+
195
+ def write_to_collection_file(content, directory)
196
+ write_to_file(content, directory, build_filename(source, nil, "yaml"))
197
+ end
198
+
199
+ def build_dirname(filename)
200
+ basename = File.basename(filename)&.gsub(/.(xml|rxl)/, "")
201
+ directory_name = sanitize_string(basename)
202
+ Dir.mkdir(directory_name) unless File.exists?(directory_name)
203
+
204
+ directory_name
205
+ end
206
+
207
+ def build_filename(file, identifier = nil, ext = "rxl")
208
+ identifier ||= Pathname.new(File.basename(file, ".xml")).to_s
209
+ [sanitize_string(identifier), options[:extension] || ext].join(".")
157
210
  end
158
211
 
159
- def build_filename(file, document)
160
- identifier = Pathname.new(File.basename(file, ".xml")).to_s
161
- filename = identifier.downcase.gsub(/^\s+/, "").gsub(/\s+$/, "").gsub(/\s+/, "-")
162
- [filename, options[:extension] || "rxl"].join(".")
212
+ def sanitize_string(string)
213
+ string.downcase.gsub("/", " ").gsub(/^\s+/, "").gsub(/\s+$/, "").
214
+ gsub(/\s+/, "-")
163
215
  end
164
216
  end
165
217
  end
@@ -1,5 +1,5 @@
1
1
  module Relaton
2
2
  module Cli
3
- VERSION = "0.1.7".freeze
3
+ VERSION = "0.1.8".freeze
4
4
  end
5
5
  end
@@ -30,7 +30,11 @@ module Relaton
30
30
  end
31
31
 
32
32
  def convert_content(content)
33
- Relaton::Bibcollection.from_xml(content)
33
+ if content.root.name == "bibdata"
34
+ Bibdata.from_xml(content.to_s)
35
+ else
36
+ Bibcollection.from_xml(content)
37
+ end
34
38
  end
35
39
 
36
40
  def file_content
@@ -4,53 +4,76 @@ require 'pp'
4
4
 
5
5
  module Relaton::Cli
6
6
  class XmlToHtmlRenderer
7
+ def initialize(liquid_dir: nil, stylesheet: nil)
8
+ @liquid_dir = liquid_dir
9
+ @stylesheet = read_file(stylesheet)
10
+ init_liquid_template_and_filesystem
11
+ end
12
+
13
+ def render(index_xml)
14
+ Liquid::Template.
15
+ parse(template).
16
+ render(build_liquid_document(index_xml))
17
+ end
18
+
19
+ def uri_for_extension(uri, extension)
20
+ unless uri.nil?
21
+ uri.sub(/\.[^.]+$/, ".#{extension.to_s}")
22
+ end
23
+ end
24
+
25
+ # Render HTML
26
+ #
27
+ # This interface allow us to convert a Relaton XML to HTML
28
+ # using the specified liquid template and stylesheets. It
29
+ # also do some minor clean during this conversion.
30
+ #
31
+ def self.render(file, options)
32
+ new(options).render(file)
33
+ end
7
34
 
8
- def initialize(options)
9
- @liquid_dir = options[:liquid_dir]
10
- @stylesheet = File.read(options[:stylesheet], encoding: "utf-8")
35
+ private
11
36
 
12
- @file_system = Liquid::LocalFileSystem.new(@liquid_dir)
13
- @template = File.read(@file_system.full_path("index"), encoding: "utf-8")
14
- Liquid::Template.file_system = @file_system
37
+ attr_reader :stylesheet, :liquid_dir, :template
38
+
39
+ def read_file(file)
40
+ File.read(file, encoding: "utf-8")
15
41
  end
16
42
 
17
- def ns(xpath)
18
- xpath.gsub(%r{/([a-zA-z])}, "/xmlns:\\1").
19
- gsub(%r{::([a-zA-z])}, "::xmlns:\\1").
20
- gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]* ?=)}, "[xmlns:\\1").
21
- gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]*\])}, "[xmlns:\\1")
43
+ def build_liquid_document(source)
44
+ bibcollection = build_bibcollection(source)
45
+
46
+ hash_to_liquid({
47
+ depth: 2,
48
+ css: stylesheet,
49
+ title: bibcollection.title,
50
+ author: bibcollection.author,
51
+ documents: document_items(bibcollection)
52
+ })
22
53
  end
23
54
 
24
- def empty2nil(v)
25
- return nil if !v.nil? && v.is_a?(String) && v.empty?
26
- v
55
+ def init_liquid_template_and_filesystem
56
+ file_system = Liquid::LocalFileSystem.new(liquid_dir)
57
+ @template = read_file(file_system.full_path("index"))
58
+
59
+ Liquid::Template.file_system = file_system
27
60
  end
28
61
 
29
62
  # TODO: This should be recursive, but it's not
30
63
  def hash_to_liquid(hash)
31
- hash.map { |k, v| [k.to_s, empty2nil(v)] }.to_h
64
+ hash.map { |key, value| [key.to_s, empty2nil(value)] }.to_h
32
65
  end
33
66
 
34
- def render(index_xml)
35
- source = Nokogiri::XML(index_xml)
36
- bibcollection = ::Relaton::Bibcollection.from_xml(source)
37
- locals = {
38
- css: @stylesheet,
39
- title: bibcollection.title,
40
- author: bibcollection.author,
41
- documents: bibcollection.to_h["root"]["items"].map { |i| hash_to_liquid(i) },
42
- depth: 2
43
- }
44
- Liquid::Template.parse(@template).render(hash_to_liquid(locals))
67
+ def empty2nil(value)
68
+ value unless value.is_a?(String) && value.empty? && !value.nil?
45
69
  end
46
70
 
47
- def uri_for_extension(uri, extension)
48
- return nil if uri.nil?
49
- uri.sub(/\.[^.]+$/, ".#{extension.to_s}")
71
+ def build_bibcollection(source)
72
+ Relaton::Bibcollection.from_xml(Nokogiri::XML(source))
50
73
  end
51
74
 
52
- def self.render(file, options)
53
- new(options).render(file)
75
+ def document_items(bibcollection)
76
+ bibcollection.to_h["root"]["items"].map { |item| hash_to_liquid(item) }
54
77
  end
55
78
  end
56
79
  end
@@ -0,0 +1,25 @@
1
+ module Relaton
2
+ module ElementFinder
3
+ attr_reader :document
4
+
5
+ def find_text(xpath, element = nil)
6
+ find(xpath, element)&.text
7
+ end
8
+
9
+ def find(xpath, element = nil)
10
+ (element || document).at(apply_namespace(xpath))
11
+ end
12
+
13
+ def find_xpath(xpath, element = nil)
14
+ element&.xpath(apply_namespace(xpath))
15
+ end
16
+
17
+ def apply_namespace(xpath)
18
+ xpath.
19
+ gsub(%r{/([a-zA-Z])}, "/xmlns:\\1").
20
+ gsub(%r{::([a-zA-Z])}, "::xmlns:\\1").
21
+ gsub(%r{\[([a-zA-Z][a-z0-9A-Z@/]* ?=)}, "[xmlns:\\1").
22
+ gsub(%r{\[([a-zA-Z][a-z0-9A-Z@/]*\])}, "[xmlns:\\1")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,87 @@
1
+ require "relaton/element_finder"
2
+
3
+ module Relaton
4
+ class XmlDocument
5
+ include Relaton::ElementFinder
6
+
7
+ def initialize(document)
8
+ @document = nokogiri_document(document) || document
9
+ end
10
+
11
+ def parse
12
+ base_attributes.merge(complex_attributes)
13
+ end
14
+
15
+ def self.parse(document)
16
+ new(document).parse
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :document
22
+
23
+ def nokogiri_document(document)
24
+ if document.class == String
25
+ Nokogiri::XML(document)&.root
26
+ end
27
+ end
28
+
29
+ def base_attributes
30
+ Hash.new.tap do |attributes|
31
+ elements.each {|key, xpath| attributes[key] = find_text(xpath) }
32
+ end
33
+ end
34
+
35
+ def complex_attributes
36
+ (date_attributes || {}).merge(
37
+ contributor_author_organization: find_organization_for('author'),
38
+ contributor_publisher_organization: find_organization_for('publisher'),
39
+ )
40
+ end
41
+
42
+ def find_organization_for(type)
43
+ find("./contributor/role[@type='#{type}']")&.parent&.
44
+ at(apply_namespace("./organization/name"))&.text
45
+ end
46
+
47
+ def elements
48
+ {
49
+ title: "./title",
50
+ stage: "./status",
51
+ script: "./script",
52
+ doctype: "./@type",
53
+ edition: "./edition",
54
+ abstract: "./abstract",
55
+ language: "./language",
56
+ uri: "./uri[not(@type)]",
57
+ rxl: "./uri[@type='rxl']",
58
+ xml: "./uri[@type='xml']",
59
+ pdf: "./uri[@type='pdf']",
60
+ doc: "./uri[@type='doc']",
61
+ html: "./uri[@type='html']",
62
+ docidentifier: "./docidentifier",
63
+ copyright_from: "./copyright/from",
64
+ copyright_owner: "./copyright/owner/organization/name",
65
+ technical_committee: "./editorialgroup/technical-committee",
66
+ contributor_author_role: "./contributor/role[@type='author']",
67
+ contributor_publisher_role: "./contributor/role[@type='publisher']",
68
+ }
69
+ end
70
+
71
+ def date_attributes
72
+ revdate =
73
+ find("./date[@type = 'published']") ||
74
+ find("./date[@type = 'circulated']") ||
75
+ find("./date")
76
+
77
+ value = find_text("./on", revdate) || find_text("./form", revdate)
78
+
79
+ if revdate && value
80
+ { datetype: revdate["type"], revdate: Date.parse(value.strip).to_s }
81
+ end
82
+ rescue
83
+ warn "[relaton] parsing published date '#{revdate.text}' failed."
84
+ { datetype: "circulated", revdate: value.strip }
85
+ end
86
+ end
87
+ end
data/relaton-cli.gemspec CHANGED
@@ -24,7 +24,6 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.required_ruby_version = ">= 2.3.0"
26
26
 
27
- spec.add_development_dependency "bundler", "~> 2.0.1"
28
27
  spec.add_development_dependency "rake", "~> 12.0"
29
28
  spec.add_development_dependency "rspec", "~> 3.0"
30
29
  spec.add_development_dependency "byebug", "~> 10.0"
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-21 00:00:00.000000000 Z
11
+ date: 2019-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 2.0.1
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 2.0.1
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: rake
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -178,11 +164,13 @@ files:
178
164
  - ".hound.yml"
179
165
  - ".rubocop.yml"
180
166
  - ".travis.yml"
167
+ - CHANGELOG.md
181
168
  - Gemfile
182
- - Gemfile.lock
183
169
  - LICENSE
184
170
  - Rakefile
171
+ - bin/console
185
172
  - bin/rspec
173
+ - bin/setup
186
174
  - docs/README.adoc
187
175
  - exe/relaton
188
176
  - i18n.yaml
@@ -198,6 +186,8 @@ files:
198
186
  - lib/relaton/cli/xml_convertor.rb
199
187
  - lib/relaton/cli/xml_to_html_renderer.rb
200
188
  - lib/relaton/cli/yaml_convertor.rb
189
+ - lib/relaton/element_finder.rb
190
+ - lib/relaton/xml_document.rb
201
191
  - relaton-cli.gemspec
202
192
  - templates/_document.liquid
203
193
  - templates/_index.liquid
data/Gemfile.lock DELETED
@@ -1,100 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- relaton-cli (0.1.7)
5
- liquid
6
- relaton (~> 0.3)
7
- thor
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- addressable (2.6.0)
13
- public_suffix (>= 2.0.2, < 4.0)
14
- algoliasearch (1.25.2)
15
- httpclient (~> 2.8, >= 2.8.3)
16
- json (>= 1.5.1)
17
- byebug (10.0.2)
18
- cnccs (0.1.3)
19
- coderay (1.1.2)
20
- diff-lcs (1.3)
21
- equivalent-xml (0.6.0)
22
- nokogiri (>= 1.4.3)
23
- gb-agencies (0.0.5)
24
- gbbib (0.4.3)
25
- cnccs (~> 0.1.1)
26
- gb-agencies (~> 0.0.1)
27
- iso-bib-item (~> 0.4.2)
28
- httpclient (2.8.3)
29
- iecbib (0.2.2)
30
- addressable
31
- iso-bib-item (~> 0.4.2)
32
- ietfbib (0.4.5)
33
- iso-bib-item (~> 0.4.2)
34
- iso-bib-item (0.4.4)
35
- isoics (~> 0.1.6)
36
- nokogiri (~> 1.8.4)
37
- ruby_deep_clone (~> 0.8.0)
38
- isobib (0.4.3)
39
- algoliasearch
40
- iecbib (~> 0.2.1)
41
- iso-bib-item (~> 0.4.2)
42
- isoics (0.1.7)
43
- json (2.1.0)
44
- liquid (4.0.1)
45
- method_source (0.9.2)
46
- mini_portile2 (2.3.0)
47
- mixlib-shellout (2.4.4)
48
- nokogiri (1.8.5)
49
- mini_portile2 (~> 2.3.0)
50
- pry (0.12.2)
51
- coderay (~> 1.1.0)
52
- method_source (~> 0.9.0)
53
- public_suffix (3.0.3)
54
- rake (12.3.2)
55
- relaton (0.3.1)
56
- algoliasearch
57
- gbbib (~> 0.4.0)
58
- iecbib (~> 0.2.0)
59
- ietfbib (~> 0.4.2)
60
- iso-bib-item (~> 0.4.2)
61
- isobib (~> 0.4.0)
62
- rspec (3.8.0)
63
- rspec-core (~> 3.8.0)
64
- rspec-expectations (~> 3.8.0)
65
- rspec-mocks (~> 3.8.0)
66
- rspec-command (1.0.3)
67
- mixlib-shellout (~> 2.0)
68
- rspec (~> 3.2)
69
- rspec-its (~> 1.2)
70
- rspec-core (3.8.0)
71
- rspec-support (~> 3.8.0)
72
- rspec-expectations (3.8.2)
73
- diff-lcs (>= 1.2.0, < 2.0)
74
- rspec-support (~> 3.8.0)
75
- rspec-its (1.2.0)
76
- rspec-core (>= 3.0.0)
77
- rspec-expectations (>= 3.0.0)
78
- rspec-mocks (3.8.0)
79
- diff-lcs (>= 1.2.0, < 2.0)
80
- rspec-support (~> 3.8.0)
81
- rspec-support (3.8.0)
82
- ruby_deep_clone (0.8.0)
83
- thor (0.20.3)
84
-
85
- PLATFORMS
86
- ruby
87
-
88
- DEPENDENCIES
89
- bundler (~> 2.0.1)
90
- byebug (~> 10.0)
91
- equivalent-xml (~> 0.6)
92
- pry
93
- rake (~> 12.0)
94
- relaton-cli!
95
- rspec (~> 3.0)
96
- rspec-command (~> 1.0.3)
97
- rspec-core (~> 3.4)
98
-
99
- BUNDLED WITH
100
- 2.0.1