我想编写一个Perl程序,使$_中的合理HTML5标记更好(“更有效” –我知道,听起来像“更怀孕”)。具体来说,我想尝试使用</p>标记正确关闭段落,就在浏览器将其关闭的地方。它是将html转换为xhtml的一步。这有助于我对全文进行后续文本分析。

HTML5规范说

  • p元素必须具有开始标签。
  • 如果在p元素后紧跟着paddressarticleasideblockquotedirdivdlfieldsetfooterformh1h2h3h4h5h6headerhrmenunavolppresectiontable元素
  • ,或者父元素中没有更多内容,并且父元素不是ul元素。

  • 问题:
  • 我认为有可能看到不正确的段落。 HTML浏览器自行推断并插入a。例如,<p>将在<h1>HEADER</h1> Now is…之前插入一个<p>。我错了吗
  • 假设HTML内容创建者已经正确插入了Now is…。我现在需要向前搜索直到结束。从26个标记中,找出一个段落的开头很容易。
  • 但是如何检测父段落中是否有更多内容?我是否可以仅从上述26个标记中搜索下一个<p>,还是需要对全栈机器进行编码(假设段落中的所有内容本身都是有效的XHTML)来检测封闭容器的结尾?

  • 感谢@Palec,我现在了解到段落在HTML中是一个奇怪的概念。尝试这个:

    <!DOCTYPE html> 
    <html> 
    <head> 
    <style> 
        p { color: blue; } 
        p:before { content:"[SP]"; } 
        p:after { content:"[EP]"; } 
    </style> 
    </head> 
     
    <body> 
     
    l0 
     
    <h1> h1 </h1> 
     
    l0 
     
    <p> para 
     
    <p> para </p> 
     
    l0 
     
    <p>para 
    <ol> 
    <li> l0 <p> para </li> 
    </ol> 
    l0 
     
    </body> 
    </html> 
    

    这表明并非所有文本都至少是一个段落。我确实将其与LaTeX概念混淆了……并认为默认情况下,“0级”处的内容是一个段落。它不是。

    请您参考如下方法:

    段落的三个概念

    HTML 5具有两个独立的概念:p元素和段落。我将此段称为结构性段。在现实世界中,我至少发现了另外两个相关概念:逻辑段落和印刷段落。

    p element 已清除。您知道的,您已经在规范中引用了它的描述。

    (Structural) paragraph 对我来说有点奇怪。屏幕阅读器或其他任何工具都可以使用它。它的定义基本上说这是phrasing content的非空运行,不会被其他类型的内容打扰(不考虑ainsdelmap)。

    逻辑段落是我认为人类认为的段落。它是一个带有单一思想的文本单元。当另一个(可能是相关的)想法开始时,该段中断并且开始一个新的想法。它由一系列句子组成。

    每个句子不仅可以具有其语言结构,而且可以包含格式。格式不限于HTML所称的措辞内容,而是我将至少添加多行预格式化的代码段,列表,数学公式(可能跨越多行,显示来自TeX的数学运算)以及可以在中间使用的任何其他内容句子之间或句子之间,同时又不中断思路。逻辑段落和其他两个概念之间的巨大区别可以在我的问题List or longer code snippet inside paragraph中看到。

    印刷段落由行的顺序而不是句子组成,并且可以包含印刷系统可以处理的所有内容。我最初认为它与逻辑段落完全相同,但事实并非如此。

    当想到时,我想到了。您可能从中知道了这一点,它只是TeX的一大堆定义,并且具有与段落相同的概念。内容一直缓冲到\par(或内部翻译为\par的空行)得到满足为止,然后将其刷新为单个段落的输出。看起来像一个(逻辑)段落在内部可以是几个段落,因为必须使用它来实现排版算法的一些更复杂的行为。从这个角度来看,它更像是一个结构段落。

    您的问题的答案

  • 如果仅存在文本节点,则(结构性)段落在h1元素之后开始。但这不是p元素。它不能使用p选择器在CSS中设置样式,它不在文档的DOM树中等。

    在某些地方元素标记不在标记中,但仍会创建元素。对于那些可以省略其开始标记的元素,情况就是如此。这些是htmlheadbodycolgrouptbody。 (至少tbody过去在HTML 4中的行为不同,此行为来自XHTML。在HTML中,它不必存在。)p元素不是这种情况。
  • 如果内容创建者未正确插入<p>(它不是有效的HTML 5),您将如何纠正它?一旦不正确,通常就无法承担任何责任。还省略了结束标记是而不是不正确!这个列表项不是一个真正的问题,所以进一步……
  • 您是否真的假设有效的XHTML 5(即HTML 5的XML序列化,特别是所有标签均已关闭)?好的,那么您需要跟踪文档树的深度信息(如果需要结构化形式的数据,则需要进行跟踪)。否则,您可能必须实施完整的HTML 5解析,例如内部带有省略的结束标记的option(在select内)。这会破坏您的深度跟踪。

    当命名的元素之一开始,遇到</p>关闭标签或遇到父元素的结尾时,该段落关闭。嗯当您仅在内部假设有效的XHTML时,您仍然需要对所有元素实施关闭规则,以便能够检测父元素的结尾……这并非易事。

  • HTML 5的HTML到XML序列化转换

    在评论中,您说过将HTML 5转换为XHTML 5是您的用例。

    不要使用正则表达式!

    正则表达式并非旨在执行诸如解析HTML之类的复杂任务。您尝试的任何事情都只是一种启发。根本没有 True regular expressions cannot parse HTML,因为HTML并不是 regular language。让我们抛开一切,Perlre更加强大;权力越大,责任就越大,如果权力不对,就不要使用权力。关于这方面的问题,这是一个真正的艺术品,它带有一个 extremely famous answer。 Jeff Atwood撰写了 more on the topic,在开头引用了这个答案,并在本文的其余部分中解释了理解您的工具的重要性。

    我认为实现此目标的文本级方法是不好的。 HTML通常被称为 tag soup,与Wikipedia所说的相反,我遇到了这个术语,指的是文本级方法来创建和修改它(即 document.write() element.innerHTML )。

    顺便说一句,这是XHTML通过废除真正解决的一件事。在JavaScript中,您不能将 document.write()与XHTML一起使用。如果可行,则说明您将HTML解析器与XHTML文档一起使用–将 Content-Type HTTP header 与 application/xhtml+xml; charset=utf-8一起使用,而不是 text/html所使用的MIME类型。

    使用DOM

    Clean Solution™是 DOM

    我相信您应该实现 HTML解析器(或使用其他实现),获取DOM树,并将序列化器写入 XHTML。如果输入文档无效,则拒绝对其进行处理。或在程序中添加开关,以告诉它如何解决解析算法无法处理的某些错误。可能有很多方法。

    我不确定如果您对规范的哪些部分不感兴趣,可以随意忽略。解析算法是标准化的,并且还指定了错误处理。您可以找到一种快捷方式,无需创建DOM树的一部分,而只需将输入的相应部分保留为未解析状态,但必须确保继续在输入的正确位置进行解析。这可能会变得凌乱,并且绝对容易出错。因此,我建议您不要这样做。

    实际解决方案

    实际上,似乎可以使用至少两个现有模块。

    Mojolicious是包含 Mojo::DOM模块的Web框架。如果不需要DOM操作,而只需要解析和序列化,则可以使用基础 Mojo::DOM::HTML。 Mojo::DOM可以使用 my $dom = Mojo::DOM->new($html_markup);解析HTML,可以将生成的DOM对象设置为通过 $dom->xml(1);使用XML序列化,并且序列化可以作为 $xhtml_markup = "$dom";$xhtml_markup = $dom->to_string();返回。来自Mojo::DOM POD:“Mojo::DOM是具有CSS选择器支持的简约且轻松的HTML / XML DOM解析器。它甚至会尝试解释损坏的XML,因此您不应将其用于验证。”在 answer by amon中使用的示例。如果您已经使用Mojolicious,则可能要使用此解决方案,否则,安装整个大型框架对于这项工作来说是过大的选择。

    HTML::HTML5::ParserHTML::HTML5::Writer模块可以分别用于HTML 5的解析和序列化。他们似乎只有几个依赖性。使用它们的漂亮代码可以在其作者 answer by tobyink中找到。对于尚未使用Mojolicious的用户来说,这应该是一个解决方案。


    评论关闭
    IT序号网

    微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!