【问题标题】:Is it possible to parse a stylesheet with Nokogiri?是否可以使用 Nokogiri 解析样式表?
【发布时间】:2010-05-30 21:45:23
【问题描述】:

我已经在谷歌上搜索了必要的两个小时,但我找不到任何好的答案,所以让我们看看人类能否击败谷歌计算机。

我想在 Ruby 中解析样式表,以便可以将这些样式应用到文档中的元素(以使样式内联)。所以,我想采取类似的东西

<style>
.mystyle {
  color:white;
}
</style>

并且能够将其提取到某种 Nokogiri 对象中。

Nokogiri 类 "CSS::Parser" (http://nokogiri.rubyforge.org/nokogiri/Nokogiri/CSS/Parser.html) 肯定有一个很有前途的名字,但我找不到任何关于它是什么或它是如何工作的文档,所以我不知道它是否能做什么我来了。

我的最终目标是能够编写如下代码:

a_web_page = Nokogiri::HTML(html_page_as_string)
parsed_styles = Nokogiri::CSS.parse(html_page_as_string)
parsed_styles.each do |style| 
  existing_inlined_style = a_web_page.css(style.declaration) || ''
  a_web_page.css(style.declaration)['css'] = existing_inlined_style + style.definition
end

这将从样式表中提取样式并将它们作为内联样式添加到我的文档中。

【问题讨论】:

    标签: css ruby nokogiri css-parsing


    【解决方案1】:

    Nokogiri 无法解析 CSS 样式表。

    您遇到的CSS::Parser 解析CSS 表达式。每当您通过 CSS 选择器而不是 XPath 遍历 HTML 树时都会使用它(这是 Nokogiri 的 cool feature)。

    不过,有一个 Ruby CSS parser。您可以将它与 Nokogiri 一起使用,以实现您想要的。

    require "nokogiri"
    require "css_parser"
    
    html = Nokogiri::HTML(html_string)
    
    css = CssParser::Parser.new
    css.add_block!(css_string)
    
    css.each_selector do |selector, declarations, specificity|
      html.css(selector).each do |element|
        style = element.attributes["style"]&.value || ""
        element.set_attribute('style', [style, declarations].compact.join(" "))
      end
    end
    

    【讨论】:

    • html.css(selector) 返回一个元素数组。所以应该是elements.each do |element|
    【解决方案2】:

    @molf 肯定有一个很好的开始,但它仍然需要调试一些问题才能使其在生产中运行。这是当前经过测试的版本:

    html = Nokogiri::HTML(html_string)
    css = CssParser::Parser.new
    css.add_block!(html_string) # Warning:  This line modifies the string passed into it.  In potentially bad ways.  Make sure the string has been duped and stored elsewhere before passing this.
    
    css.each_selector do |selector, declarations, specificity|
      next unless selector =~ /^[\d\w\s\#\.\-]*$/ # Some of the selectors given by css_parser aren't actually selectors.
      begin
        elements = html.css(selector)
        elements.each do |match|
          match["style"] = [match["style"], declarations].compact.join(" ")
        end
      rescue
        logger.info("Couldn't parse selector '#{selector}'")
      end
    end
    
    html_with_inline_styles = html.to_s 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-27
      • 1970-01-01
      • 2010-11-24
      • 2011-03-17
      • 2014-06-19
      • 1970-01-01
      相关资源
      最近更新 更多