使用Nokogiri替换HTML占位符标记

时间:2017-09-25 21:59:23

标签: ruby-on-rails templates html-parsing nokogiri

我的特定用例是构建具有占位符值的HTML电子邮件模板,这些模板稍后会被实际数据替换。

示例:

hello <span class='placeholder' data-slug='contact.name'>contact.name</span>

...替换占位符时成为“Hello John”。

我有50多个占位符,并且使用Nokogiri用实时数据替换占位符:

placeholder_mappings = {
  "contact.name" => @contact.name,
  "contact.email" => @contact.email,
  ...
}

text = "hello <span class='placeholder' data-slug='contact.name'>contact.name</span>"

page = Nokogiri::HTML(text)

placeholder_mappings.each do |key, value|
  page.css("[data-slug='#{key}']").each do |node|
    node.replace(value)
  end
end

page.to_html

我使用HTML标签而不是{{contact.first_name}}之类的原因是我可以将CSS添加到占位符中,以便用户在构建模板时可以轻松地看到它们。否则,我会使用gsub并使其变得简单:)

我上面的代码有效,但似乎效率低下。我看过Nokogiri文档,但我承认节点解析对我来说是一个新手,我需要一些时间才能掌握术语。

有没有更高效的方法来实现这一点,还是我的问题有更好的解决方案,我不知道?

1 个答案:

答案 0 :(得分:1)

基于您的方法的一些输入。您可以通过不迭代哈希placeholder_mappings来改进,而是根据键获取值:

  page.css('span.placeholder').each do |node|
    node.replace(@placeholder_mappings[node['data-slug']])
  end

或使用at_css

  node = page.at_css('span.placeholder')
  node.replace(@placeholder_mappings[node['data-slug']])

似乎您当前的方法是分别处理每个占位符。一次运行整个模板可能会更快:

  nodes = page.css('span.placeholder')
  nodes.each do |node|
    node.content = @placeholder_mappings[node['data-slug']]
  end
  nodes.remove_class("placeholder")

这里我不会替换整个节点,因为这会使迭代变得困难。相反,我只是替换内容,然后删除最后的.placeholder以删除CSS。