2017-09-25 51 views
0

我的特殊用例是构建具有占位符值的HTML电子邮件模板,这些模板稍后将替换为实际数据。使用Nokogiri替换HTML占位符标记

例子:

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

...变成 “你好,约翰的” 占位符被替换时。

我有这些占位符的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

基于您的方法的一些输入。

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']]) 

看来你目前的做法是分别处理每个占位符:可以通过散列placeholder_mappings不迭代,并基于密钥,而不是获取的价值做出一些改进。这可能是更快一气呵成贯穿整个模板:

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

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

+0

我不敢相信我没有想到只参考使用的映射!这应该更具性能,因为大多数模板只能使用10个左右不同的占位符。关于不删除节点,问题是,如果我离开'span'标签并仅删除'class',电子邮件客户端是否会在主题行中输出原始字符串'hello '。 –