module ReDuxml

Attributes

e[R]
src_doc[R]

Public Instance Methods

resolve(doc_or_node, parent_params={}) click to toggle source

@param doc_or_node [Doc, String] XML to load; can be Doc, String path or String XML; also XML Element when recursing @return [Doc] instantiated XML with parameters resolved with given values

# File lib/re_duxml.rb, line 13
def resolve(doc_or_node, parent_params={})
  @e ||= Evaluator.new
  if doc_or_node.is_a?(Element)
    resolved_node = doc_or_node.stub
    resolved_node.attributes.each do |attr, val|
      resolved_node[attr] = resolve_str(val, parent_params)
    end
    this_params = get_params(doc_or_node, parent_params)
    new_children = doc_or_node.nodes.collect do |child|
      if child.respond_to?(:nodes) # if this node is an XML element...
        new_child = child.clone
        new_child[:if] = resolve_str(new_child[:if], this_params) if new_child[:if]
        if new_child.if? # if this node should exist
          new_child[:if] = nil if new_child[:if] == 'true'
          child_params = get_params(new_child, this_params)
          new_instances = new_child.activate
          i = -1
          new_instances.collect do |inst|
            i += 1
            resolve(inst, child_params.merge({'iterator' => i.to_s}))
          end
        end
      else # this is a text node
        resolve_str(child, this_params)
      end
    end.flatten.compact
    resolved_node << new_children
  else
    @src_doc = get_doc doc_or_node
    @doc = Doc.new << resolve(src_doc.root, parent_params)
  end
end

Private Instance Methods

find_close_parens_index(str) click to toggle source

finds index of close parentheses corresponding to first open parentheses found in given str

# File lib/re_duxml.rb, line 67
def find_close_parens_index(str)
  levels = 0
  index = 0
  str.each_char do |char|
    case char
      when '(' then
        levels += 1
      when ')' then
        levels -= 1
      else
    end
    return index if levels == 0
    index += 1
  end
  raise Exception, "cannot find end of parameter expression!"
end
find_exprs(str) click to toggle source

@param str [String] string that may contain parameter expression e.g. 'asdf @(param + 2) asdf' @return [Array] array of macro strings e.g. 'asdf @(param + 2) asdf' => 'param + 2'

# File lib/re_duxml.rb, line 107
def find_exprs(str)
  expressions = []
  str.scan('@(') do |c|
    expr_start_index = $~.offset(0)[0] # gets index of current match
    expr_end_index = find_close_parens_index str[expr_start_index+1..-1]
    expressions << str[expr_start_index+2, expr_end_index-1]
  end
  expressions
end
get_params(node, param_hash) click to toggle source
# File lib/re_duxml.rb, line 50
def get_params(node, param_hash)
  if node.nodes.any? and !node.text? and node.nodes[0].name == 'duxml:parameters'
    local_params = {}
    params = node[0].nodes.clone
    params.each do |param|
      new_val = resolve_str(param[:value], param_hash)
      node[0].delete param unless new_val.parameterized?
      local_params[param[:name]] = new_val
    end
    node.delete node[0] unless node[0].nodes.any?
    param_hash.merge local_params
  else
    param_hash
  end
end
resolve_str(content_str, param_hash) click to toggle source

@param content_str [String] string that may contain parameterized expressions e.g. “a @(var0+var1) string @(var2)” @param param_hash [Hash] keys are parameter names, values are parameter values e.g. {var0: 'param', var1: 'eter'} @return [String] content_str with parameter values substituted and algebraically reduced if any unknown parameters remain e.g. 'a parameter string @(var2)'

# File lib/re_duxml.rb, line 87
def resolve_str(content_str, param_hash)
  output_str = content_str.clone
  questions = find_exprs content_str
  return output_str if questions.empty?
  questions.each do |question|
    reply = Macro.new e.evaluate(question, param_hash).to_s
    replacement_str = if reply.parameterized?
        reply.to_s
      else
        macro_value = reply.demacro
        Regexp.string.match(macro_value) ? macro_value[1..-2] : macro_value
      end
    macro_string = Macro.new(question).macro_string
    output_str.gsub!(macro_string, replacement_str)
  end
  output_str
end