Nokogiri 生成无效的 HTML



我需要处理一个HTML文档并在几个地方插入一些节点。我正在处理的内容无效,但Nokogiri足够聪明,可以弄清楚它应该是什么。问题是我不想更改原始文档的格式,除了我插入的部分。

下面是一个示例:

require 'nokogiri'
orig_html = '
  <html>
  <meta name="Generator" content="Microsoft Word 97 O.o">
  <body>
    1
    <b><p>2</p></b>
    3
  </body>
</html>'
puts Nokogiri::HTML(orig_html).inner_html
# >> <html>
# >> <head>
# >> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
# >> <meta name="Generator" content="Microsoft Word 97 O.o">
# >> </head>
# >> <body>
# >>         1
# >>         <b></b><p>2</p>
# >>         3
# >>       </body>
# >> </html>

我希望输出与输入相同。问题是我不能在<b>里面有<p>.我倾向于切换到XML,但是有无效的标签,例如<meta>标签,它没有关闭.HTML足够聪明,可以识别这一点,但XML不是。

>Nokogiri正在修复格式错误的HTML,以使其可解析。完成后,DOM 处于合理状态,但原始文档不再可从 Nokogiri 获得。

如果你想让原件保持不变,你必须在把它传递给Nokogiri之前让它有效,然后你可以使用Nokogiri的方法操纵它。通常,我会使用一些正则表达式来查找故障点并添加/调整标签或其关联的结束标签,以允许 Nokogiri 无需修复即可解析。

这不是HTML比XML更聪明的情况,而是Nokogiri尊重XML规范的精神,这是严格的,并通过在文件无效时用错误填充errors数组来引发标志。HTML的规范不那么严格,而且,因为浏览器在解析和显示HTML时(太)宽容,Nokogiri在某种程度上遵循,进行修正,然后填充errors数组。(无论哪种情况,您都可以检查该数组以查看出了什么问题。

require 'nokogiri'
orig_html = '
  <html>
  <meta name="Generator" content="Microsoft Word 97 O.o">
  <body>
    1
    <b><p>2</p></b>
    3
  </body>
</html>'
doc = Nokogiri::HTML(orig_html)
doc.errors

doc.errors包含:

[
    [0] #<Nokogiri::XML::SyntaxError: Unexpected end tag : b>
]

以下是我如何使用Nokogiri来修复您的示例HTML:

doc = Nokogiri::HTML(orig_html)
p = doc.at('b+p')
p.previous_sibling.remove

这是此时的 HTML:

<!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">
<meta name="Generator" content="Microsoft Word 97 O.o">
</head>
<body>
    1
    <p>2</p>
    3
  </body>
</html>

继续:

p.inner_html = "<b>#{p.content}</b>"
puts doc.to_html

这是生成的 HTML:

<!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">
<meta name="Generator" content="Microsoft Word 97 O.o">
</head>
<body>
    1
    <p><b>2</b></p>
    3
  </body>
</html>

很明显,示例 HTML 并不是您真正使用的,因此您必须更改访问器以找到需要更改的标签,但这应该可以让您继续前进。

上述方法适用于上述特定情况,但不适用于以下情况。

    orig_html = '
      <html>
      <meta name="Generator" content="Microsoft Word 97 O.o">
      <body>
        1
        <b>this is a bold
          <p>This is a paragraph</p>
        </b>
        3
      </body>
    </html>'
    doc = Nokogiri::HTML(orig_html)
    p = doc.at('b+p')
    p.previous_sibling.remove
    p.inner_html = "<b>#{p.content}</b>" # !> mismatched indentations at 'end' with 'def' at 17
     puts doc.to_html

生成的 HTML:

   <!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">
    <meta name="Generator" content="Microsoft Word 97 O.o">
    </head>
    <body>
        1
         <p><b>This is a paragraph</b></p>
        3
      </body>
    </html>

相关内容

  • 没有找到相关文章

最新更新