2014-09-23 93 views
4

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

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

但是增加了标签。我也试着

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

为“How to prevent Nokogiri from adding <DOCTYPE> tags?”的建议,但删除任何<html><head>,或者<body>标签是在文档中。

如果它的事项,我读文件代码:

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

我需要做一个gsub事前,因为我需要更换<tmpl_var>标签这不是正确的HTML,并导致更多的问题。

使用HTML.fragment(r)时,出现htmlParseStartTag: misplaced <html> tag错误(以及<body><head>的类似错误)。

有没有办法阻止它做出这些增加?

一个例子的转换:

之前:

<!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.fragment或之后:使用解析

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

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

<div> 
    Stuff 
</div> 

在这种情况下,我希望它只输出前一节。 (在真正的脚本中,我做了一堆更改)。

+0

您的“之前”或“之后”部分没有任何地方显示您要替换的标签。相反,它看起来像是在问两个不同的问题。 – 2014-09-23 16:46:43

+0

更换标签是一个不同的问题,我已经解决了一个问题。现在我只关注停止添加doctype标签。 tmpl_var与这个问题无关,我只是把它作为直接拷贝到我如何将文件读入Nokogiri中,以防直接使用String来代替文件。 – CSturgess 2014-09-23 16:49:44

+0

如果temple_var的东西不相关,那么你甚至不应该记录或提及它,因为它是[红鲱鱼](http://en.wikipedia.org/wiki/Red_herring)。 – 2014-09-23 17:14:20

回答

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

但是你仍然可以Munge时间的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剥离<html>标签时解析一个片段?我不知道。它独自离开<body>如果<head><html>丢失:

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>" 

但它变得时髦,如果<head><html>存在:

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的错误给我,因为我还没有看到任何记录该行为的东西。

+0

和Html.fragment一样。如果您提供的HTML包含''标记,它将删除它们。 – CSturgess 2014-09-23 16:08:58

+0

您的编辑仍不能解决问题。 标签在我甚至到达Nokogiri之前就已经被gsub删除了。它们不相关。我需要替换很多标签,我可以做,并且需要递归。这些标签不是问题,请注意我的Before/After示例不包含它们。我需要知道如何让Nokogiri不添加新标签,同时不会删除已经在html中的head,html和body标签。 – CSturgess 2014-09-23 16:53:35

+0

我认为你需要[把它带到Nokogiri作者](https://github.com/sparklemotion/nokogiri),因为它就像一个bug。 – 2014-09-23 17:32:45

2

你可以通过使用Nokogiri::XML::DocumentFragment而不是Nokogiri::HTML::DocumentFragment来解决这个问题。 XML版本不会删除html,head或body标签。