class CSL::Parser

A relatively straightforward XML parser that parses CSL using either Nokogiri or REXML.

Attributes

engines[R]
parser[RW]

Public Class Methods

new() click to toggle source
# File lib/csl/parser.rb, line 27
def initialize
  require 'nokogiri'
  @parser = Parser.engines[:nokogiri]
rescue LoadError
  require 'rexml/document'
  @parser = Parser.engines[:default]
end

Public Instance Methods

parse(*arguments) click to toggle source
# File lib/csl/parser.rb, line 35
def parse(*arguments)
  parse!(*arguments)
rescue
  nil
end
parse!(source, scope = Node) click to toggle source
# File lib/csl/parser.rb, line 41
def parse!(source, scope = Node)
  root = parser[source].children.detect { |child| !skip?(child) }
  parse_tree root, scope
end

Private Instance Methods

comment?(node) click to toggle source
# File lib/csl/parser.rb, line 93
def comment?(node)
  node.respond_to?(:comment?) && node.comment? ||
    node.respond_to?(:node_type) &&
    [:comment, :xmldecl, :processing_instruction, 7].include?(node.node_type)
end
parse_attributes(node) click to toggle source
# File lib/csl/parser.rb, line 60
def parse_attributes(node)
  Hash[*node.attributes.map { |n, a|
    [n.to_sym, a.respond_to?(:value) ? a.value : a.to_s]
  }.flatten]
end
parse_node(node, scope = Node) click to toggle source
# File lib/csl/parser.rb, line 48
def parse_node(node, scope = Node)
  attributes, text = parse_attributes(node), parse_text(node)

  if text
    n = TextNode.create node.name, attributes
    n.text = text
    n
  else
    scope.create node.name, attributes
  end
end
parse_text(node) click to toggle source
# File lib/csl/parser.rb, line 79
def parse_text(node)
  if node.respond_to?(:has_text?)
    node.has_text? && node.text
  else
    child = node.children[0]
    return unless child && child.respond_to?(:text?) && child.text?

    text = child.text
    return if text.to_s.strip.empty?

    text
  end
end
parse_tree(node, scope = Node) click to toggle source
# File lib/csl/parser.rb, line 66
def parse_tree(node, scope = Node)
  return nil if node.nil?

  root = parse_node node, scope
  scope = specialize_scope(root, scope)

  node.children.each do |child|
    root << parse_tree(child, scope) unless skip?(child)
  end unless root.textnode?

  root
end
skip?(node) click to toggle source
# File lib/csl/parser.rb, line 107
def skip?(node)
  comment?(node) || text?(node)
end
specialize_scope(root, scope = Node) click to toggle source
# File lib/csl/parser.rb, line 111
def specialize_scope(root, scope = Node)
  case root
  when Style
    Style
  when Locale
    Locale
  when Info
    Info
  else
    scope
  end
end
text?(node) click to toggle source
# File lib/csl/parser.rb, line 99
def text?(node)
  if defined?(Nokogiri)
    node.is_a?(Nokogiri::XML::Text)
  else
    false
  end
end