我正在使用nokogiri解析一个html文件并对其进行修改,然后将其输出到这样的文件中:
htext= File.open(inputOpts.html_file).read
h_doc = Nokogiri::HTML(htext)
File.open(outputfile, 'w+') do |file|
file.write(h_doc)
end
输出文件包含第一行:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
我不希望这样,因为我将html嵌入到另一个文件中,而且此标记导致了问题。
问题是如何从h_doc中删除它。
答案 0 :(得分:4)
根据您要执行的操作,您可以将HTML解析为DocumentFragment
:
h_doc = Nokogiri::HTML::DocumentFragment.parse(htext)
在片段上调用to_s
或to_html
时,将省略doctype行,Nokogiri添加的<html>
和<body>
标记也会被省略本。
答案 1 :(得分:3)
这取决于您的需求。如果您需要的只是身体那么
h_doc.at_xpath("//body") #this will just pull the data from the <body></body> tags
如果您还需要收集<head>
,请避开<DOCTYPE>
然后
#this will capture everything between the <head></head> and <body></body> tags
h_doc.xpath("//head") + h_doc.xpath("//body")
这样的事情
h_doc = Nokogiri::HTML(open(input_opts.html_file))
File.open(outputfile,'w+') do |file|
#for just <body>
file << h_doc.at_xpath("//body").to_s
#for <head> and <body>
file << (h_doc.xpath("//head") + h_doc.xpath("//body")).to_s
end
body
的通知我使用了#at_xpath
因为这会返回Nokogiri::Element
,但在合并它们时我使用了#xpath
,因为这将返回Nokogiri::XML::NodeSet
。不用担心这部分只是用于组合而且html会出现相同的情况,例如: h_doc.at_xpath("//head").to_s == h_doc.xpath("//head").to_s #=> true
答案 2 :(得分:0)
读取输入文件时可以忽略第一行:
htext= File.readlines(inputOpts.html_file)[1..-1].join
h_doc = Nokogiri::HTML(htext)
File.open(outputfile, 'w+') do |file|
file.write(h_doc)
end
答案 3 :(得分:0)
我设法同时使用HTML::Document
和HTML::DocumentFragment
来解决此问题。
对于背景,我使用Nokogiri解析和修改HTML的“模板”,“部分”和/或“组件”。这意味着我遇到的文件不是有效的HTML文档。相反,它们是由我使用的框架整理在一起的HTML文档的一部分。
供参考,HTML::Document
添加<!DOCTYPE>
声明,还将文档包装到<html>
和<body>
实体中(如果它们尚未出现在文档中)。同样,HTML::DocumentFragment
将用<p>
实体包裹您的片段。
我没有花太多时间去挖掘Nokogiri库代码来了解这些附加实体的位置,而是决定接受这种自以为是的实现并加以解决。
这是我写出修改后的HTML的方式:
html_str = doc.xpath("//body").children.to_html(encoding: 'UTF-8')
File.open(_filename, 'w') {|f| f.write(html_str)}
这似乎比应该做的难。我什至尝试使用SaveOptions
设置save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
无济于事。
在任何情况下,尽管按我的喜好此解决方案都有些麻烦,但它仍然有效。