ドキュメントを HTML ではなく XML として作成すると、Nokogiri は空の要素をスラッシュで閉じて出力します。これは HTML5 で有効です。<source />
html = Nokogiri.HTML('')
puts html.create_element('source')
#=> <source></source>
xml = Nokogiri.XML('')
puts xml.create_element('source')
#=> <source/>
ただし、これの欠点は、有効な HTML5 ドキュメントを XML として解析すると、解析でエラーが発生することです。
require 'nokogiri'
html5 = '<!DOCTYPE html>
<html><head>
<meta charset="utf-8">
<title>Test</title>
</head><body>
<img src="a.jpg"><img src="b.jpg">
</body></html>'
doc = Nokogiri.XML( html5, &:noblanks )
puts doc
#=> <?xml version="1.0"?>
#=> <!DOCTYPE html>
#=> <html>
#=> <head>
#=> <meta charset="utf-8">
#=> <title>Test</title>
#=> </meta>
#=> <body>
#=> <img src="a.jpg">
#=> <img src="b.jpg">
#=> </img>
#=> </img>
#=> </body>
#=> </head>
#=> </html>
これを修正するには、void 要素をセルフクローズしてソースを有効な XML にする必要があります (これは HTML5 でも有効です)。さらに、XML 宣言を回避するには、DTD とルートを別々にシリアル化する必要があります。
require 'nokogiri'
html5 = '<!DOCTYPE html>
<html><head>
<meta charset="utf-8"/>
<title>Test</title>
</head><body>
<img src="a.jpg"/><img src="b.jpg"/>
</body></html>'
doc = Nokogiri.XML( html5, &:noblanks )
puts doc.children.map(&:to_s)
#=> <!DOCTYPE html>
#=> <html>
#=> <head>
#=> <meta charset="utf-8"/>
#=> <title>Test</title>
#=> </head>
#=> <body>
#=> <img src="a.jpg"/>
#=> <img src="b.jpg"/>
#=> </body>
#=> </html>