【问题标题】:Recursive Contents of HTML tag using regex使用正则表达式的 HTML 标记的递归内容
【发布时间】:2014-04-03 00:28:55
【问题描述】:

我正在为我的客户编写一个应用程序,它使用 WYSIWYG 允许员工修改带有某些变量的信函模板,这些变量被解析为写信给客户的信息。

WYSIWYG 生成 HTML,我将其保存到 SQL 服务器数据库中。然后,我使用 PHP 类生成带有模板文本的 PDF 文档。

这是我的问题。 PDF 生成类可以翻译 b,u,i HTML 标签。而已。这基本上没问题,除了我也需要翻译块引用。我认为最好的解决方案是编写一个正则表达式语句,获取每个 blockquote HTML 块的内容,并用五个空格替换块中的每一行。诀窍是一些块引用可能包含嵌套块引用(双缩进,等等)

但不幸的是,我对正则表达式一向不太熟悉,在过去的 1.5 小时里我尝试了不同的模式,但没有任何效果。

这里有一些问题:

  • 字符串可能包含也可能不包含块引用块
  • 字符串可以包含多个块引用
  • 字符串可能包含任何级别的块引用块嵌套
  • 我们可以依赖 HTML 格式正确

一个示例输入字符串看起来像这样:

Dear Charlie,<br><br>We are contacting you because blah blah blah blah.<br><br><br>To login, please use this information:<blockquote>Username: someUsername<br>Password: somePassword</blockquote><br><br>Thank you.

为了简单的解决方案,我需要将每个块引号内的每个 HTML 中断替换为 5 个空格,然后是 \n 换行符。

【问题讨论】:

  • 在解决 RegEx 问题时,修改 PDF 创建器似乎比 mickey-mouse 更实用。这是您正在使用的闭源库,还是可以修改的?
  • @Brad It's this class -> ros.co.nz/pdf
  • 你确实实现了“blockquote indent”!==“intent 5 spaces at the beginning of the line”对吧?
  • 虽然我意识到它不像“5 个空格”那么简单,但这可能是在 PDF 文档中模拟块引用的最简单方法,因为它会打印出每个空格(与 HTML 处理空格的方式不同)。我将用来模拟效果的空格数量可能会被调整或最终变成使用 \t 字符。我仍处于试验阶段,只需要让它“工作”

标签: php regex


【解决方案1】:

您可能想查看PHP Simple HTML DOM Parser。您可以使用它将输入解析为 HTML DOM 树并使用它。

【讨论】:

  • 如果一切都失败了,我同意这一点。解析为 HTML 文档,然后将其“反向解析”回数据库。
【解决方案2】:
~<blockquote>((?:[^<]*+(?:(?!<blockquote>)|(?R))*+)*+)</blockquote>~

您需要使用preg_replace_callback 递归地运行这个正则表达式:

const REGEX_BLOCKQUOTE = '~<blockquote>((?:[^<]*+(?:(?!<blockquote>)|(?R))*+)*+)</blockquote>~';
function blockquoteCallback($matches) {
    return doIndent(preg_replace_callback(REGEX_BLOCKQUOTE, __FUNCTION__, $matches[1]));
}

$output = preg_replace_callback(REGEX_BLOCKQUOTE, 'blockQuoteCallback', $input);

我的正则表达式假设,块引用或其他任何地方不会有任何属性。

(PS:我会把“使用 DOM 解析器”的评论留给其他人。)

【讨论】:

    【解决方案3】:

    正则表达式有一个theory behind them,即使现代的正则表达式引擎提供了一个'Type - 2.5'级别的语言,有些事情仍然不可行。在您的特殊情况下,嵌套不容易实现。 解释这一点的一种简单方法是说正则表达式不能保持计数.. 即他们无法计算嵌套级别...

    您需要的是有限的 CFG(paren-counting 类型).. 您需要以某种方式保持计数..可能是堆栈或树...

    【讨论】:

    • PHP 使用的正则表达式风格 (PCRE) 允许以多种方式进行递归。使用反向引用捕获组(?n) 或使用递归子组(?R)
    • @nikic by 'Type -2.5' 我想到了 pcre .. 我不知道 php 已经切换到它 .. 但是 regexp 看起来很麻烦......如果解决方案涉及编写一个函数和在其中递归,使用
      和 \n 作为分隔符进行标记,并进行简单的扫描可能是一个更易读的解决方案!
    猜你喜欢
    • 2012-04-04
    • 2011-11-14
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多