lib/fb2rb.rb in fb2rb-0.2.1 vs lib/fb2rb.rb in fb2rb-0.3.0
- old
+ new
@@ -10,11 +10,11 @@
module FB2rb
FB2_NAMESPACE = 'http://www.gribuser.ru/xml/fictionbook/2.0'
XLINK_NAMESPACE = 'http://www.w3.org/1999/xlink'
# Holds data of a single FB2 file
- class Book
+ class Book # rubocop:disable Metrics/ClassLength
# @return [Array<FB2rb::Stylesheet>]
attr_accessor(:stylesheets)
# @return [FB2rb::Description]
attr_accessor(:description)
# @return [Array<FB2rb::Body>]
@@ -27,44 +27,69 @@
@bodies = bodies
@description = description
@stylesheets = stylesheets
end
- # Reads existing FB2 file from an IO object, and creates new Book object.
- # @return [FB2rb::Book]
- def self.read(filename_or_io)
- Zip::InputStream.open(filename_or_io) do |zis|
- while (entry = zis.get_next_entry)
- next if entry.directory?
+ class << self
+ # Reads existing compressed FB2 file from an IO object, and creates new Book object.
+ # @return [FB2rb::Book, nil]
+ def read_compressed(filename_or_io)
+ Zip::InputStream.open(filename_or_io) do |zis|
+ while (entry = zis.get_next_entry)
+ next if entry.directory?
- xml = Nokogiri::XML::Document.parse(zis)
- fb2_prefix = ns_prefix(FB2rb::FB2_NAMESPACE, xml.namespaces)
- xlink_prefix = ns_prefix(FB2rb::XLINK_NAMESPACE, xml.namespaces)
- return parse(xml, fb2_prefix, xlink_prefix)
+ xml = Nokogiri::XML::Document.parse(zis)
+ fb2_prefix = ns_prefix(FB2rb::FB2_NAMESPACE, xml.namespaces)
+ xlink_prefix = ns_prefix(FB2rb::XLINK_NAMESPACE, xml.namespaces)
+ return parse(xml, fb2_prefix, xlink_prefix)
+ end
end
end
- end
- def self.ns_prefix(namespace, namespaces)
- prefix = namespaces.key(namespace)
- prefix.nil? ? nil : prefix.sub(/^xmlns:/, '')
- end
+ # Reads existing uncompressed FB2 file from an IO object, and creates new Book object.
+ # @return [FB2rb::Book]
+ def read_uncompressed(filename_or_io)
+ xml = read_xml(filename_or_io)
+ fb2_prefix = ns_prefix(FB2rb::FB2_NAMESPACE, xml.namespaces)
+ xlink_prefix = ns_prefix(FB2rb::XLINK_NAMESPACE, xml.namespaces)
+ parse(xml, fb2_prefix, xlink_prefix)
+ end
- # @return [FB2rb::Book]
- def self.parse(xml, fb2_prefix, xlink_prefix) # rubocop:disable Metrics/MethodLength
- Book.new(
- Description.parse(xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:description"), fb2_prefix, xlink_prefix),
- xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:body").map do |node|
- Body.parse(node)
- end,
- xml.xpath("#{fb2_prefix}:FictionBook/#{fb2_prefix}:binary").map do |node|
- Binary.parse(node)
- end,
- xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:stylesheet").map do |node|
- Stylesheet.parse(node)
+ def ns_prefix(namespace, namespaces)
+ prefix = namespaces.key(namespace)
+ prefix.nil? ? nil : prefix.sub(/^xmlns:/, '')
+ end
+
+ private
+
+ # @return [FB2rb::Book]
+ def parse(xml, fb2_prefix, xlink_prefix) # rubocop:disable Metrics/MethodLength
+ Book.new(
+ Description.parse(
+ xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:description"), fb2_prefix, xlink_prefix
+ ),
+ xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:body").map do |node|
+ Body.parse(node)
+ end,
+ xml.xpath("#{fb2_prefix}:FictionBook/#{fb2_prefix}:binary").map do |node|
+ Binary.parse(node)
+ end,
+ xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:stylesheet").map do |node|
+ Stylesheet.parse(node)
+ end
+ )
+ end
+
+ def read_xml(filename_or_io)
+ if filename_or_io.respond_to? :read
+ Nokogiri::XML::Document.parse(filename_or_io)
+ else
+ File.open(filename_or_io, 'rb') do |io|
+ return Nokogiri::XML::Document.parse(io)
+ end
end
- )
+ end
end
def to_xml(xml) # rubocop:disable Metrics/MethodLength
xml.FictionBook('xmlns' => FB2rb::FB2_NAMESPACE,
'xmlns:l' => 'http://www.w3.org/1999/xlink') do
@@ -89,12 +114,12 @@
add_binary_io name, io, content_type
end
end
end
- # Writes FB2 to file or IO object. If file exists, it will be overwritten.
- def write(filename_or_io = StringIO.new)
+ # Writes compressed FB2 to file or IO object. If file exists, it will be overwritten.
+ def write_compressed(filename_or_io = StringIO.new)
if filename_or_io.respond_to?(:write)
Zip::OutputStream.write_buffer(filename_or_io) do |zos|
write_to_zip(zos)
end
else
@@ -102,10 +127,26 @@
write_to_zip(zos)
end
end
end
+ # Writes FB2 (uncompressed) to file or IO object specified by the argument.
+ def write_uncompressed(filename_or_io = StringIO.new) # rubocop:disable Metrics/MethodLength
+ data = (Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
+ to_xml(xml)
+ end).to_xml
+
+ if filename_or_io.respond_to?(:write)
+ filename_or_io.write(data)
+ else
+ File.open(filename_or_io, 'wb') do |io|
+ io.write(data)
+ end
+ end
+ filename_or_io
+ end
+
private
def write_to_zip(zos)
mod_time = Zip::DOSTime.now
unless (tm = description.document_info.date.value).nil?
@@ -113,26 +154,17 @@
end
# TODO: entry name
mimetype_entry = Zip::Entry.new(nil, 'book.fb2', nil, nil, nil, nil, nil, nil, mod_time)
zos.put_next_entry(mimetype_entry, nil, nil, Zip::Entry::DEFLATED)
- write_to_stream(zos)
+ write_uncompressed(zos)
end
def add_binary_io(name, io, content_type = nil)
io.binmode
content = io.read
@binaries << Binary.new(name, content, content_type)
self
- end
-
- # Writes FB2 (uncompressed) to stream specified by the argument.
- def write_to_stream(io)
- builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
- to_xml(xml)
- end
- xml = builder.to_xml
- io.write(xml)
end
end
# Holds <description> data
class Description