【问题标题】:Get str_replace to avoid replacing selected tags获取 str_replace 以避免替换选定的标签
【发布时间】:2016-10-31 06:49:22
【问题描述】:

我在下面有这段代码,它在用户问题中找到小于和大于 HTML 字符实体,并用合适的实体名称替换它们

$string = $this->input->post('question');

$find_and_replace = array(
    '<' => '&lt;',
    '>' => '&gt;',
);

$new_data = str_replace(array_keys($find_and_replace), array_values($find_and_replace), $string);

当问题中有&amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;code&amp;gt;&amp;lt;/code&amp;gt;之类的标签时

它也替换了它们 &amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;code&amp;gt;&amp;lt;/code&amp;gt;

我不希望这种情况发生只是为了替换标签内的内容。

问题我怎样才能仍然使用 str_replace 但只能使用内容 在 pre 标签或 code 标签内。

public function preview() {
    $data = array('success' => false, 'question' => '', 'tag' => '');

    if ($_POST) {

        $string = $this->input->post('question');

        $find_and_replace = array(
            '<' => '&lt;',
            '>' => '&gt;',
        );

        $new_data = str_replace(array_keys($find_and_replace), array_values($find_and_replace), $string);

        $data['question'] = $new_data;

        $data['success'] = true;
    }

    $this->output
    ->set_content_type('application/json')
    ->set_output(json_encode($data));
}

function get_everything_in_tags($string, $tagname)
{
    $pattern = "#<\s*?$tagname\b[^>]*>(.*?)</$tagname\b[^>]*>#s";
    preg_match($pattern, $string, $matches);
    return $matches[1];
}

【问题讨论】:

  • 我不想删除前置标签,我只是希望它避免在前置标签周围替换 &lt;&gt;

标签: php codeigniter


【解决方案1】:

你可以像这样使用preg_replace_callback

$new_data = preg_replace_callback("#</?(pre|code)>|[<>]#", function ($match) {
    return $match[0] == '<' ? '&lt;' : ($match[0] == '>' ? '&gt;' : $match[0]);
}, $string);

它将保留&lt;pre&gt;&lt;code&gt; 开始和结束标记,并且只替换其他&lt;&gt; 字符。

请注意,通常替换方法并不是处理 HTML 的理想方式。您可以查看 DOMDocument 来解析 HTML 并获取 HTML 字符串中元素的文本内容。

【讨论】:

    【解决方案2】:
    strip_tags($input, '<pre>');
    

    DEMO

    更新&lt;pre&gt;&lt;/pre&gt;&lt;code&gt;&lt;/code&gt;块之外替换&lt;&gt;

    $pattern = array(
        "(<(pre|code)(?:\s+\w+(?:=\w+|\"[^\"]+\"|'[^']+')?)*>.*?</(pre|code)>(*SKIP)(*FAIL)"
        ."|<)is",
        "(<(pre|code)(?:\s+\w+(?:=\w+|\"[^\"]+\"|'[^']+')?)*>.*?</(pre|code)>(*SKIP)(*FAIL)"
        ."|>)is",
    );
    $replacement = array("&lt;", "&gt", "&lt;", "&gt");
    $out = preg_replace($pattern, $replacement, $input);
    echo htmlspecialchars($out);
    

    http://phpio.net/s/60t

    【讨论】:

    • abouts 适合哪些功能?
    • 因为我不想删除 pre 标签,我只是希望它避免在 pre 标签周围替换 &lt;&gt;
    【解决方案3】:

    如果您知道您将解析大型文本字符串,那么使用 MB(兆字节长度字符串)包中的函数将是最有效的。比如……

    $input = "<b>Hello!</b>";
    $conversion_bit_mask = [
        0x003c, 0x003c, 0, 0xffff, // < sign
        0x003e, 0x003e, 0, 0xffff, // > sign
    ];
    $input_cleansed = mb_encode_numericentity($input, $conversion_bit_mask, $format);
    print($input_cleansed); // output is: &gt;b&lt;Hello!&gt;/b&lt;
    

    【讨论】:

      猜你喜欢
      • 2015-04-05
      • 2014-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-24
      • 1970-01-01
      • 2011-09-07
      相关资源
      最近更新 更多