Skip to content

Instantly share code, notes, and snippets.

@lucasluitjes
Last active November 26, 2017 21:34
Show Gist options
  • Save lucasluitjes/8a78f01465943f8abe334b4feea6cfd3 to your computer and use it in GitHub Desktop.
Save lucasluitjes/8a78f01465943f8abe334b4feea6cfd3 to your computer and use it in GitHub Desktop.
require 'parser/current'
require 'rexml/document'
class XMLAST
include REXML
attr_reader :doc
def initialize sexp
@doc = Document.new "<root></root>"
@sexp = sexp
root = @doc.root
populate_tree(root, sexp)
end
def populate_tree xml, sexp
if sexp.is_a?(String) ||
sexp.is_a?(Symbol) ||
sexp.is_a?(Numeric) ||
sexp.is_a?(NilClass)
el = Element.new(sexp.class.to_s.downcase + "-val")
el.add_attribute 'value', sexp.to_s
xml.add_element el
else
el = Element.new(sexp.type.to_s)
el.add_attribute('id', sexp.object_id)
sexp.children.each{ |n| populate_tree(el, n) }
xml.add_element el
end
end
def treewalk sexp=@sexp
return sexp unless sexp&.respond_to?(:children)
[sexp, sexp.children.map {|n| treewalk(n) }].flatten
end
def xpath path
results = XPath.match(doc, path)
results.map do |n|
if n.respond_to?(:attributes) && n.attributes['id']
treewalk.find do |m|
m.object_id.to_s == n.attributes['id']
end
else
n
end
end
end
end
# snippet = 'f.text_field :attr, placeholder: "placeholder text"'
# exp = Parser::CurrentRuby.parse(snippet)
# xml = XMLAST.new(exp)
# xml.xpath('*/send/hash/pair[sym[symbol-val/@value="placeholder"]]/str')
# => [s(:str, "placeholder text")]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment