【问题标题】:PHP - Inner HTML recursive replacePHP - 内部 HTML 递归替换
【发布时间】:2014-02-12 13:28:38
【问题描述】:

我需要在 HTML 的一部分上执行递归 str_replace(递归我的意思是首先是内部节点),所以我写道:

$str = //get HTML;
$pttOpen = '(\w+) *([^<]{1,100}?)';
$pttClose = '\w+';
$pttHtml = '(?:(?!(?:<x-)).+)';

while (preg_match("%<x-(?:$pttOpen)>($pttHtml)*</x-($pttClose)>%m", $str, $match)) {
    list($outerHtml, $open, $attributes, $innerHtml, $close) = $match;
    $newHtml = //some work....
    str_replace($outerHtml, $newHtml, $str);
}

这个想法是首先替换非嵌套的 x-tags。 但它只有在innerHtml 在开始标签的同一行时才有效(所以我想我误解了 /m 修饰符的作用)。我不想使用 DOM 库,因为我只需要简单的字符串替换。有什么帮助吗?

【问题讨论】:

  • 您能否在您的问题中添加一个具有预期输出的示例?
  • @CasimiretHippolyte 几乎同时出现同样的问题! :)
  • 修饰符 m 将锚点 ^$(您不使用)的含义更改为“行首”和“行尾”。
  • 您使用$newHTML 所做的“工作”也很有用。
  • 对 HTML 代码的操作 -> 始终使用 DOM 解析器,而不是正则表达式。 (xpath, domdocument, simplexml, sax..)

标签: php regex innerhtml


【解决方案1】:

试试这个正则表达式:

%<x-(?P<open>\w+)\s*(?P<attributes>[^>]*)>(?P<innerHtml>.*)</x-(?P=open)>%s

演示

http://regex101.com/r/nA2zO5

示例代码

$str = // get HTML
$pattern = '%<x-(?P<open>\w+)\s*(?P<attributes>[^>]*)>(?P<innerHtml>.*)</x-(?P=open)>%s';

while (preg_match($pattern, $str, $matches)) {
    $newHtml =  sprintf('<ns:%1$s>%2$s</ns:%1$s>', $matches['open'], $matches['innerHtml']);
    $str = str_replace($matches[0], $newHtml, $str);
}

echo htmlspecialchars($str);

输出

最初,$str 包含以下文本:

<x-foo>
    sdfgsdfgsd
       <x-bar>
           sdfgsdfg
       </x-bar>
       <x-baz attr1='5'>
           sdfgsdfg
       </x-baz>
    sdfgsdfgs
</x-foo>

结果是:

<ns:foo>
   sdfgsdfgsd
   <ns:bar>
       sdfgsdfg
   </ns:bar>
   <ns:baz>
       sdfgsdfg
   </ns:baz>
   sdfgsdfgs
</ns:foo>

因为,我不知道 $newHtml 做了什么工作,所以我以某种方式模仿这项工作,将 x- 替换为 ns: 并删除任何属性。

【讨论】:

  • @CasimiretHippolyte 我已经用你的评论更新了我的答案。
【解决方案2】:

感谢@Alex,我想出了这个:

%<x-(?P<open>\w+)\s*(?P<attributes>[^>]*?)>(?P<innerHtml>((?!<x-).)*)</x-(?P=open)>%is

如果没有 ((?! 在 innerHtml 模式中,它将无法与嵌套标签一起使用(它将首先匹配外部标签,这不是我通缉)。这样最里面的首先匹配。希望这会有所帮助。

【讨论】:

    【解决方案3】:

    我不确切知道您要进行什么样的更改,但这是我将继续进行的方式:

    $pattern = <<<'EOD'
    ~
        <x-(?<tagName>\w++) (?<attributes>[^>]*+) >
        (?<content>(?>[^<]++|<(?!/?x-))*) #by far more efficient than (?:(?!</?x-).)*
        </x-\g<tagName>>
    ~x
    EOD;
    
    function callback($m) { // exemple function
        return '<n-' . $m['tagName'] . $m['attributes'] . '>' . $m['content']
             . '</n-' . $m['tagName'] . '>';       
    };
    
    do {
        $code = preg_replace_callback($pattern, 'callback', $code, -1, $count);
    } while ($count);
    
    
    echo htmlspecialchars(print_r($code, true));
    

    【讨论】:

    • @Alex:它介于 Yves Saint Laurent 和 Wordpress 之间。
    • @Alex:当然!
    猜你喜欢
    • 2011-05-09
    • 2019-04-21
    • 1970-01-01
    • 2013-07-09
    • 2020-09-05
    • 2018-04-15
    • 1970-01-01
    • 2010-11-07
    • 2011-09-03
    相关资源
    最近更新 更多