【问题标题】:Stop Nokogiri from adding DOCTYPE and meta tags?阻止 Nokogiri 添加 DOCTYPE 和元标记?
【发布时间】:2014-11-17 21:06:50
【问题描述】:

我正在尝试使用 Nokogiri 将一些模板文件从一种格式转换为另一种格式。但它不断添加标签。我试图阻止它添加 Doctype 和元标记,但无法弄清楚。我试过了

@doc = Nokogiri::HTML.parse(r)

但这会添加标签。我也试过了

@doc = Nokogiri::HTML.fragment(r)

按照“How to prevent Nokogiri from adding <DOCTYPE> tags?”中的建议,但会删除文档中的任何 &lt;html&gt;&lt;head&gt;&lt;body&gt; 标记。

如果重要的话,我读取文件的代码是:

f = File.read(infile)
r = f.gsub(/<tmpl_var ([^>]*)>/, '{{{\1}}}')
@doc = Nokogiri::HTML.fragment(r)

我需要事先做一个gsub,因为我需要替换&lt;tmpl_var&gt;标签,这些标签不是正确的HTML,会导致更多问题。

使用HTML.fragment(r) 时,我确实收到htmlParseStartTag: misplaced &lt;html&gt; tag 错误(以及&lt;body&gt;&lt;head&gt; 的类似错误)。

有没有办法阻止它添加这些内容?

转换示例:

之前:

<html>
    <head>
        <script>
            var x = "y";
        </script>
    </head>
    <body>
        <div>
            Stuff
        </div>
   </body>
</html>

使用 Parse 后:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script>
            var x = "y";
        </script>
    </head>
    <body>
        <div>
            Stuff
        </div>
    </body>
</html>

使用HTML.fragmentHTML::DocumentFragment.parse后:

<script>
    var x = "y";
</script>

<div>
    Stuff
</div>

在这种情况下,我希望它只输出之前的部分。 (虽然在实际脚本中我做了很多更改)。

【问题讨论】:

  • 在您的“之前”或“之后”部分中没有显示您要替换的标签。相反,您似乎在问两个不同的问题。
  • 替换标签是另一个问题,我已经解决了。现在我只专注于阻止它添加 doctype 标签。 tmpl_var 的东西与这个问题无关,我只是把它作为我如何将文件读入 Nokogiri 的直接副本放在那里,以防使用字符串而不是文件直接重要。
  • 如果 Temple_var 不相关,那么您甚至不应该记录或提及它,因为它是 red herring
  • “我只是把它作为我如何将文件读入 Nokogiri 的直接副本保存在那里,以防使用字符串而不是文件直接很重要。”如果您在documentation for parsing 中四处寻找,您会看到诸如“string_or_io 可能是一个字符串,或者任何响应读取和关闭的对象,例如 IO 或 StringIO。”之类的语句。

标签: html ruby nokogiri


【解决方案1】:

您可以使用Nokogiri::XML::DocumentFragment 而不是Nokogiri::HTML::DocumentFragment 来解决此问题。 XML 版本不会删除 html、head 或 body 标记。

【讨论】:

    【解决方案2】:

    Nokogiri 可以被告知不要添加标准的 HTML 标头。考虑这些:

    require 'nokogiri'
    
    doc = Nokogiri::HTML('<p>foo</p>')
    doc.to_html # => "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body><p>foo</p></body></html>\n"
    
    doc = Nokogiri::HTML.fragment('<p>foo</p>')
    doc.to_html # => "<p>foo</p>"
    

    tmpl_var 在 HTML 中是一个错误的标签名称,{{{\1}}} 也是如此,因此让 Nokogiri 尝试解析其中任何一个都会导致问题:

    doc = Nokogiri::HTML.fragment('<templ_var p1="baz">foo</templ_var>')
    doc.errors # => [#<Nokogiri::XML::SyntaxError: Tag templ_var invalid>]
    

    但你仍然可以使用 DOM:

    doc.to_html # => "<templ_var p1=\"baz\">foo</templ_var>"
    doc.search('templ_var').each { |t| t.name = 'bar'}
    doc.to_html # => "<bar p1=\"baz\">foo</bar>"
    

    或者:

    doc.to_html # => "<div><templ_var p1=\"baz\">foo</templ_var></div>"
    doc.search('templ_var').each { |t| t.replace('{{{\1}}}') }
    doc.to_html # => "<div>{{{\\1}}}</div>"
    

    把这些东西放在一起,再加上一点诡计:

    doc = Nokogiri::HTML.fragment('<div><templ_var p1="baz">foo</templ_var></div>')
    
    doc.to_html # => "<div><templ_var p1=\"baz\">foo</templ_var></div>"
    
    doc.search('templ_var').each { |t| t.replace('{{{\1}}}') }
    doc.to_html # => "<div>{{{\\1}}}</div>"
    
    header = Nokogiri::XML.fragment('<html><body>')
    header.at('body').children = doc
    header.to_html # => "<html><body><div>{{{\\1}}}</div></body></html>"
    

    所以,我会去追求它。

    现在,为什么 Nokogiri 在解析片段时会剥离&lt;html&gt; 标签?我不知道。如果&lt;head&gt;&lt;html&gt; 丢失,它会留下&lt;body&gt;

    Nokogiri::HTML.fragment('<p>foo<p>').to_html 
    # => "<p>foo</p><p></p>"
    Nokogiri::HTML.fragment('<body><p>foo<p></body>').to_html 
    # => "<body>\n<p>foo</p>\n<p></p>\n</body>"
    

    但如果存在&lt;head&gt;&lt;html&gt;,它就会变得很时髦:

    Nokogiri::HTML.fragment('<head><style></style></head><body><p>foo<p></body>').to_html 
    # => "<style></style><p>foo</p><p></p>"
    Nokogiri::HTML.fragment('<html><head><style></style></head><body><p>foo<p></body></html>').to_html 
    # => "<style></style><p>foo</p><p></p>"
    

    对我来说,这闻起来像是 Nokogiri 中的一个错误,因为我没有看到任何可以记录这种行为的东西。

    【讨论】:

    • 这与 Html.fragment 的作用相同。如果您提供的 HTML 包含 &lt;html&gt; 标记,它将删除它们。
    • 您的修改仍不能解决问题。 标签在我到达 Nokogiri 之前就被 gsub 删除了。它们不相关。我需要替换很多标签,我可以做到,而且它需要是递归的。这些标签不是问题,请注意我的之前/之后示例不包括它们。我需要知道如何让 Nokogiri 不添加新标签,同时不删除 html 中已有的 head、html 和 body 标签。
    • 我认为你需要take it to the Nokogiri authors,因为它就像一个错误。
    • 看起来不像。 parse 的源代码似乎表明它应该忽略这些标签。不过我找到了一个解决方案,使用 XML 而不是 HTML。
    猜你喜欢
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    相关资源
    最近更新 更多