Class: Arrolio::GenericAdapter

Inherits:
Object
  • Object
show all
Includes:
DocumentExtraction, FootnoteExtraction, HeadingExtraction, InlineRunCollection, ListConversion, MetadataExtraction, TableConversion
Defined in:
lib/arrolio/generic_adapter.rb,
lib/arrolio/generic_adapter/list_conversion.rb,
lib/arrolio/generic_adapter/table_conversion.rb,
lib/arrolio/generic_adapter/heading_extraction.rb,
lib/arrolio/generic_adapter/document_extraction.rb,
lib/arrolio/generic_adapter/footnote_extraction.rb,
lib/arrolio/generic_adapter/metadata_extraction.rb,
lib/arrolio/generic_adapter/inline_run_collection.rb

Overview

Generic, configuration-driven XML adapter. Reads a set of declarative rules (YAML) that describe how to parse a specific document format's presentation XML into a Content::Document.

A flavor is defined entirely by:

adapter_rules.yml  — element selectors, mappings, style resolution
layout_spec.yml    — styles, page templates, flows
flow_rules.yml     — page sequence structure, cover layout

No Ruby code is needed for a new flavor. The adapter has ZERO hard-coded element names — every XML element/attribute the adapter touches is named in the rules' selectors block.

Defined Under Namespace

Modules: DocumentExtraction, FootnoteExtraction, HeadingExtraction, InlineRunCollection, ListConversion, MetadataExtraction, TableConversion

Constant Summary collapse

DEFAULT_SELECTORS =
{
  'heading' => 'fmt-title',
  'heading_depth_attribute' => 'depth',
  'list_item' => 'li',
  'list_item_label' => 'fmt-name',
  'paragraph' => 'p',
  'term_number' => 'fmt-name',
  'term_preferred' => 'fmt-preferred',
  'term_definition' => 'fmt-definition',
  'term_source' => 'fmt-termsource',
  'note_label' => 'fmt-name',
  'figure_image' => 'image',
  'figure_caption' => 'fmt-name',
  'figure_caption_fallback' => 'name',
  'table_row' => 'tr',
  'table_cell' => ['td', 'th'].freeze,
  'table_header' => 'thead',
  'table_body' => 'tbody',
  'biblio_tag' => 'biblio-tag',
  'biblio_formattedref' => 'formattedref',
  'image_src_attribute' => 'src',
  'image_alt_attribute' => 'alt',
  'id_attribute' => 'id',
  'autonum_class' => 'fmt-autonum-delim',
  'stem' => 'stem',
  'stem_formatted' => 'fmt-stem',
  'math' => 'math',
  'preface_container' => 'preface',
  'preface_children' => ['clause', 'foreword'].freeze,
  'bibliography_container' => 'bibliography',
  'bibliography_reference' => 'references',
  'bibliography_item' => 'bibitem',
  'fallback_title' => 'title',
  'span' => 'span',
  'tab_inline' => 'tab',
  'break_inline' => 'br'
}.freeze
CONVERTER_REGISTRY =

Maps content_type (declared in rules.element_mapping) to a builder method. Adding a new content type = adding one entry here plus a builder method below — convert_children itself never needs to change (Open/Closed Principle).

{
  'section' => :convert_section,
  'paragraph' => :convert_paragraph,
  'table' => :convert_table,
  'figure' => :convert_figure,
  'list' => :convert_list,
  'term' => :convert_term,
  'note' => :convert_note,
  'example' => :convert_example,
  'preformatted' => :convert_preformatted
}.freeze
XREF_ELEMENTS =
['fmt-xref-label', 'fmt-xref', 'xref'].freeze

Constants included from InlineRunCollection

InlineRunCollection::UNICODE_SPACES

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from TableConversion

#cell_runs_with_footnotes, #convert_table, #convert_table_rows, #extract_table_caption, #table_footnote

Methods included from DocumentExtraction

#extract_bibliography, #extract_preface, #extract_sections, #extract_title_block, #title_block_runs

Methods included from MetadataExtraction

#derive_metadata_fields, #extract_cover, #extract_metadata

Methods included from ListConversion

#convert_definition_list, #convert_list

Methods included from HeadingExtraction

#clause_level, #extract_from_heading, #extract_heading, #walk_heading_text

Methods included from InlineRunCollection

#collect_inline_runs, #format_locality_text, #normalize_text, #serialize_element_to_xml, #walk_math, #walk_stem

Methods included from FootnoteExtraction

#extract_footnotes, #footnote_body_paragraphs

Constructor Details

#initialize(rules:, layout_spec: nil) ⇒ GenericAdapter

Returns a new instance of GenericAdapter.



98
99
100
101
102
# File 'lib/arrolio/generic_adapter.rb', line 98

def initialize(rules:, layout_spec: nil)
  @rules = rules.is_a?(String) ? YAML.safe_load_file(rules) : rules
  @layout_spec = layout_spec
  @selectors = DEFAULT_SELECTORS.merge(@rules['selectors'] || {})
end

Instance Attribute Details

#layout_specObject (readonly)

Returns the value of attribute layout_spec.



96
97
98
# File 'lib/arrolio/generic_adapter.rb', line 96

def layout_spec
  @layout_spec
end

#rulesObject (readonly)

Returns the value of attribute rules.



96
97
98
# File 'lib/arrolio/generic_adapter.rb', line 96

def rules
  @rules
end

#selectorsObject (readonly)

Returns the value of attribute selectors.



96
97
98
# File 'lib/arrolio/generic_adapter.rb', line 96

def selectors
  @selectors
end

Instance Method Details

#convert(xml) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/arrolio/generic_adapter.rb', line 104

def convert(xml)
  xml = xml.read if xml.is_a?(IO) || xml.is_a?(StringIO)
  xml = xml.to_s.dup.force_encoding('UTF-8').scrub
  rexml = xml.is_a?(REXML::Document) ? xml : REXML::Document.new(xml)
  root = rexml.root

  Content::Document.new(
    metadata: (root),
    sections: extract_sections(root),
    preface: extract_preface(root),
    bibliography: extract_bibliography(root),
    cover: extract_cover(root),
    footnotes: extract_footnotes(root),
    title_block: extract_title_block(root)
  )
end