使用 Nokogiri 替换标签 - 更快的方法?
Replace tags using Nokogiri - quicker way?
我在名为 html_data
的变量中有以下 HTML,我希望用 <a>
标签和 src
参数替换 <img>
标签"img" 标签成为 "a" 标签的 href
。
现有HTML:
<!DOCTYPE html>
<html>
<head>
<title>Learning Nokogiri</title>
</head>
<body marginwidth="6">
<div valign="top">
<div class="some_class">
<div class="test">
<img src="apple.png" alt="Apple" height="42" width="42">
<div style="white-space: pre-wrap;"></div>
</div>
</div>
</div>
</body>
</html>
这是我的解决方案A:
nokogiri_html = Nokogiri::HTML(html_data)
nokogiri_html("img").each { |tag|
a_tag = Nokogiri::XML::Node.new("a", nokogiri_html)
a_tag["href"] = tag["src"]
tag.add_next_sibling(a_tag)
tag.remove()
}
puts 'nokogiri_html is', nokogiri_html
这是我的解决方案B:
nokogiri_html = Nokogiri::HTML(html_data)
nokogiri_html("img").each { |tag|
tag.name= "a";
tag.set_attribute("href" , tag["src"])
}
puts 'nokogiri_html is', nokogiri_html
虽然解决方案 A 工作正常,但我正在寻找是否有 quicker/direct 使用 Nokogiri 替换标签的方法。使用解决方案 B,我的 "img" 标签确实被 "a" 标签取代,但 "img" 标签的属性仍然保留在 "a" 标签内。以下是解决方案 B 的结果:
<!DOCTYPE html>
<html>
<body>
<p>["\n", "\n", " </p>
\n", "
<title>Learning Nokogiri</title>
\n", " \n", " \n", "
<div valign='\"top\"'>
\n", "
<div class='\"some_class\"'>
\n", "
<div class='\"test\"'>
\n", " <a src="%5C%22apple.png%5C%22" alt='\"Apple\"' height='\"42\"' width='\"42\"' href="%5C%22apple.png%5C%22"></a>\n", "
<div style='\"white-space:' pre-wrap></div>
\n", "
</div>
\n", "
</div>
\n", "
</div>
\n", " \n", ""]
</body>
</html>
有没有一种方法可以使用 Nokogiri 更快地替换 HTML 中的标签?另外如何删除结果中的“\n”?
首先,请将您的示例数据 (HTML) 剥离到演示问题所需的最少数量。
这里是做你想做的事情的基础:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<!DOCTYPE html>
<html>
<body>
<img src="apple.png" alt="Apple" height="42" width="42">
</body>
</html>
EOT
doc.search('img').each do |img|
src, alt = %w[src alt].map{ |p| img[p] }
img.replace("<a href='#{ src }'>#{ alt }</a>")
end
doc.to_html
# => "<!DOCTYPE html>\n<html>\n <body>\n <a href=\"apple.png\">Apple</a>\n </body>\n</html>\n"
puts doc.to_html
# >> <!DOCTYPE html>
# >> <html>
# >> <body>
# >> <a href="apple.png">Apple</a>
# >> </body>
# >> </html>
这样做可以让 Nokogiri 干净利落地替换节点。
没有必要做所有这些繁琐的事情:
a_tag = Nokogiri::XML::Node.new("a", nokogiri_html)
a_tag["href"] = tag["src"]
tag.add_next_sibling(a_tag)
tag.remove()
相反,创建一个字符串作为您要使用的标签,然后让 Nokogiri 将字符串转换为节点并替换旧节点:
src, alt = %w[src alt].map{ |p| img[p] }
img.replace("<a href='#{ src }'>#{ alt }</a>")
没有必要去除节点之间多余的空白。它会影响 HTML 的外观,但浏览器会吞噬多余的空白而不显示它。
Nokogiri 可以被告知不要输出节点间空白,从而导致 compressed/fugly 输出,但如何做到这一点是一个单独的问题。
我在名为 html_data
的变量中有以下 HTML,我希望用 <a>
标签和 src
参数替换 <img>
标签"img" 标签成为 "a" 标签的 href
。
现有HTML:
<!DOCTYPE html>
<html>
<head>
<title>Learning Nokogiri</title>
</head>
<body marginwidth="6">
<div valign="top">
<div class="some_class">
<div class="test">
<img src="apple.png" alt="Apple" height="42" width="42">
<div style="white-space: pre-wrap;"></div>
</div>
</div>
</div>
</body>
</html>
这是我的解决方案A:
nokogiri_html = Nokogiri::HTML(html_data)
nokogiri_html("img").each { |tag|
a_tag = Nokogiri::XML::Node.new("a", nokogiri_html)
a_tag["href"] = tag["src"]
tag.add_next_sibling(a_tag)
tag.remove()
}
puts 'nokogiri_html is', nokogiri_html
这是我的解决方案B:
nokogiri_html = Nokogiri::HTML(html_data)
nokogiri_html("img").each { |tag|
tag.name= "a";
tag.set_attribute("href" , tag["src"])
}
puts 'nokogiri_html is', nokogiri_html
虽然解决方案 A 工作正常,但我正在寻找是否有 quicker/direct 使用 Nokogiri 替换标签的方法。使用解决方案 B,我的 "img" 标签确实被 "a" 标签取代,但 "img" 标签的属性仍然保留在 "a" 标签内。以下是解决方案 B 的结果:
<!DOCTYPE html>
<html>
<body>
<p>["\n", "\n", " </p>
\n", "
<title>Learning Nokogiri</title>
\n", " \n", " \n", "
<div valign='\"top\"'>
\n", "
<div class='\"some_class\"'>
\n", "
<div class='\"test\"'>
\n", " <a src="%5C%22apple.png%5C%22" alt='\"Apple\"' height='\"42\"' width='\"42\"' href="%5C%22apple.png%5C%22"></a>\n", "
<div style='\"white-space:' pre-wrap></div>
\n", "
</div>
\n", "
</div>
\n", "
</div>
\n", " \n", ""]
</body>
</html>
有没有一种方法可以使用 Nokogiri 更快地替换 HTML 中的标签?另外如何删除结果中的“\n”?
首先,请将您的示例数据 (HTML) 剥离到演示问题所需的最少数量。
这里是做你想做的事情的基础:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<!DOCTYPE html>
<html>
<body>
<img src="apple.png" alt="Apple" height="42" width="42">
</body>
</html>
EOT
doc.search('img').each do |img|
src, alt = %w[src alt].map{ |p| img[p] }
img.replace("<a href='#{ src }'>#{ alt }</a>")
end
doc.to_html
# => "<!DOCTYPE html>\n<html>\n <body>\n <a href=\"apple.png\">Apple</a>\n </body>\n</html>\n"
puts doc.to_html
# >> <!DOCTYPE html>
# >> <html>
# >> <body>
# >> <a href="apple.png">Apple</a>
# >> </body>
# >> </html>
这样做可以让 Nokogiri 干净利落地替换节点。
没有必要做所有这些繁琐的事情:
a_tag = Nokogiri::XML::Node.new("a", nokogiri_html)
a_tag["href"] = tag["src"]
tag.add_next_sibling(a_tag)
tag.remove()
相反,创建一个字符串作为您要使用的标签,然后让 Nokogiri 将字符串转换为节点并替换旧节点:
src, alt = %w[src alt].map{ |p| img[p] }
img.replace("<a href='#{ src }'>#{ alt }</a>")
没有必要去除节点之间多余的空白。它会影响 HTML 的外观,但浏览器会吞噬多余的空白而不显示它。
Nokogiri 可以被告知不要输出节点间空白,从而导致 compressed/fugly 输出,但如何做到这一点是一个单独的问题。