Php 使用正则表达式递归HTML标记的内容

Php 使用正则表达式递归HTML标记的内容,php,regex,Php,Regex,我正在为我的客户编写一个应用程序,该应用程序使用所见即所得(WYSIWYG)允许员工使用某些变量修改信函模板,这些变量被解析为信函所针对的客户的信息 所见即所得生成HTML,我将其保存到SQL server数据库中。然后,我使用PHP类生成带有模板文本的PDF文档 这是我的问题。PDF生成类可以翻译b、u、i HTML标记。就这样。这基本上是好的,除了我需要块报价被翻译了。我认为最好的解决方案是编写一个regex语句,即获取每个blockquote HTML块的内容,并用五个空格替换块内的每一行

我正在为我的客户编写一个应用程序,该应用程序使用所见即所得(WYSIWYG)允许员工使用某些变量修改信函模板,这些变量被解析为信函所针对的客户的信息

所见即所得生成HTML,我将其保存到SQL server数据库中。然后,我使用PHP类生成带有模板文本的PDF文档

这是我的问题。PDF生成类可以翻译b、u、i HTML标记。就这样。这基本上是好的,除了我需要块报价被翻译了。我认为最好的解决方案是编写一个regex语句,即获取每个blockquote HTML块的内容,并用五个空格替换块内的每一行。诀窍是某些块引号可能包含嵌套的块引号(双缩进,等等)

但不幸的是,我从来都不太熟悉正则表达式,在过去的1.5个小时里,我一直在尝试不同的模式,但什么都没用

以下是哥特西亚人:

  • 字符串可能包含也可能不包含blockquote块
  • 字符串可以包含多个块引号
  • 字符串可能包含块引号块的任何嵌套级别
  • 我们可以相信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.
亲爱的Charlie,

我们之所以联系您,是因为诸如此类。

要登录,请使用以下信息:用户名:someUsername
密码:somePassword

谢谢。
为了简化解决方案,我需要用5个空格替换每个blockquote中的每个HTML分隔符,然后是换行符。

您可能需要签出。您可以使用它来解析HTML DOM树的输入并使用它。

您可能想要签出。您可以使用它来解析HTML DOM树的输入并使用它

~<blockquote>((?:[^<]*+(?:(?!<blockquote>)|(?R))*+)*+)</blockquote>~
我的正则表达式假设blockquote或其他任何地方都不会有任何属性

(注:我将把“使用DOM解析器”的注释留给其他人。)

我的正则表达式假设blockquote或其他任何地方都不会有任何属性


(注:我将把“使用DOM解析器”的注释留给其他人。)

正则表达式有一个新的定义,尽管现代正则表达式引擎提供的是“类型-2.5”级别的语言,但有些事情仍然不可行。在局部情况下,嵌套不容易实现。 解释这一点的一个简单方法是,正则表达式不能保持计数。。 i、 他们无法计算嵌套水平

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

正则表达式有一个值,即使现代正则表达式引擎可以提供“Type-2.5”级别的语言,但有些事情仍然不可行。在局部情况下,嵌套不容易实现。 解释这一点的一个简单方法是,正则表达式不能保持计数。。 i、 他们无法计算嵌套水平

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

在正则表达式问题上修改PDF创建者似乎比米老鼠更实际。这是您正在使用的封闭源代码库,还是可修改的库?@Brad It’s this class->您是否实现了“blockquote缩进”!==“行首有5个空格”对吗?虽然我意识到这不像“5个空格”那么简单,但这可能是在打印每个空格时模拟PDF文档中块引号的最简单方法(与HTML处理空格的方式不同)。我将要用来模拟效果的空间量可能会被调整或最终变成使用\t字符。我仍处于试验阶段,只需要让它“正常工作”,在正则表达式的问题上修改PDF创建者似乎比米老鼠更实际。这是您正在使用的封闭源代码库,还是可修改的库?@Brad It’s this class->您是否实现了“blockquote缩进”!==“行首有5个空格”对吗?虽然我意识到这不像“5个空格”那么简单,但这可能是在打印每个空格时模拟PDF文档中块引号的最简单方法(与HTML处理空格的方式不同)。我将要用来模拟效果的空间量可能会被调整或最终变成使用\t字符。我仍处于试验阶段,只需要让它“工作”,如果其他一切都失败了,我同意这一点。解析到一个HTML文档,然后将其“反向解析”回数据库。如果所有其他操作都失败,我同意这一点。解析一个HTML文档,然后将其“反向解析”回数据库。使用反向引用捕获组
(?n)
,或通过“Type-2.5”使用resursion子组
(?R)
@nikic,我考虑了pcre。。我不知道php已经切换到它了。。然而,regexp看起来很复杂。。。若解决方案涉及编写函数并在其中递归,那个么使用and和\n作为分隔符标记,并进行简单扫描可能是一个更具可读性的解决方案!PHP使用的正则表达式风格(PCRE)允许以多种方式进行递归。使用反向引用捕获组
(?n)
,或通过“Type-2.5”使用resursion子组
(?R)
@nikic,我考虑了pcre。。我不知道php已经切换到它了。。然而,regexp看起来很复杂。。。若解决方案涉及编写函数并在其中递归,那个么使用and和\n作为分隔符标记,并进行简单扫描可能是一个更具可读性的解决方案!
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);