PHP |复制不包括标题属性的特定单词
PHP | Replicate specific word excluding the title attribute
我正在尝试替换“自定义”一词并用 <span> custom </span>
复制它。
使用 str_replace ()
函数它可以工作,但这也会在 title 属性中替换它,我不希望发生这种情况,因为 title 中的 span 标记是一个错误。
如何在不触及标题属性的情况下替换“自定义”一词?
这是我的代码:
$oldText = "custom";
$newText = "<span>custom</span>";
$string = "<a href='#' title='Products custom'>Products custom</a>";
str_ireplace($oldText, $newText,$string);
这只是一个例子。
custom这个词也可以放在字符串的中间或者开头...
谢谢
您可能必须使用 PHP's DOM parser 才能做到这一点。写一个正则表达式来解决它并不适用于所有情况。
A) DOM
我会从 开始,然后稍微更改一下以完成您想要做的事情。当您将 custom
替换为 <span>custom</span>
时,您将创建一个新的 DOM 元素。替换文本内容将不起作用,因为 <span>
将被转义并替换为 <span>
。
所以我会这样做:
使用preg_match_all()和/\bcustom\b/
等模式来获取文本中找到的项目的所有偏移量:
// Search for the word, but delimited by word boundaries to
// avoid matching 'custom' in 'customization' or 'customer'.
$pattern = '/\b' . preg_quote($word_to_search) . '\b/';
if (preg_match_all($pattern, $child->wholeText, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) {
var_export($matches);
}
将这些以字节为单位的偏移量转换为以字符为单位的偏移量(这是因为 UTF-8 可以有 1 个或 n 个字节的字符):
function char_offset($string, $byte_offset, $encoding = null)
{
$substr = substr($string, 0, $byte_offset);
return mb_strlen($substr, $encoding ?: mb_internal_encoding());
}
使用DOMText::splitText()将文本节点拆分为两个文本节点,偏移量以字符为单位。
使用 DOMDocument::createElement()
创建一个 <span>
元素
$new_text = 'custom'; // or whatever.
$spanElement = $domNode->ownerDocument->createElement('span', $new_text);
- 的第二个文本节点之前插入此跨度元素
更正第二个文本节点以删除开头的 custom
单词。
B) 使用正则表达式
但是如果你的案例总是在 <a>
标签中,那么你可以尝试这样的事情:https://regex101.com/r/ksPqxe/1
正则表达式的解释请看右栏的说明。如果需要,您可以删除 case-insensitive 的 i
标志。使用 s
标志以便 .
也匹配新行。我不得不使用带有 .*?
而不是 .*
的非贪婪搜索。所以最后我使用 U
作为 Ungreedy 标志,然后使用 .*
.
此解决方案无法处理 link 中多个 custom
个单词的情况。但你可能只有一次。如果需要,则使用一个正则表达式获取 link 的文本内容,然后使用第二个正则表达式将 custom
的所有实例替换为 <span>custom</span>
.
<?php
$pattern = '/(<a[^>]*>.*)\bcustom\b(.*<\/a>)/isU';
// Or without the ungreedy flag:
//$pattern = '/(<a[^>]*>.*?)\bcustom\b(.*?<\/a>)/is';
$substitution = '<span>custom</span>';
$inputs = [
"<a href='#' title='Products custom'>Products custom</a>",
'<a href="https://www.customer.com" title="customer" data-type="custom">Custom stuff</a>',
'<a href=\"https://www.customer.com\" title=\"customer"
data-type="custom">Customer stuff</a>',
'<a href="#">customize it!</a>',
];
$results = [];
foreach ($inputs as $input) {
$result = preg_replace($pattern, $substitution, $input);
$results[] = "$input\n$result\n";
}
print implode(str_repeat('-', 80) . "\n", $results);
输出:
<a href='#' title='Products custom'>Products custom</a>
<a href='#' title='Products custom'>Products <span>custom</span></a>
--------------------------------------------------------------------------------
<a href="https://www.customer.com" title="customer" data-type="custom">Custom stuff</a>
<a href="https://www.customer.com" title="customer" data-type="custom"><span>custom</span> stuff</a>
--------------------------------------------------------------------------------
<a href=\"https://www.customer.com\" title=\"customer"
data-type="custom">Customer stuff</a>
<a href=\"https://www.customer.com\" title=\"customer"
data-type="custom">Customer stuff</a>
--------------------------------------------------------------------------------
<a href="#">customize it!</a>
<a href="#">customize it!</a>
我正在尝试替换“自定义”一词并用 <span> custom </span>
复制它。
使用 str_replace ()
函数它可以工作,但这也会在 title 属性中替换它,我不希望发生这种情况,因为 title 中的 span 标记是一个错误。
如何在不触及标题属性的情况下替换“自定义”一词?
这是我的代码:
$oldText = "custom";
$newText = "<span>custom</span>";
$string = "<a href='#' title='Products custom'>Products custom</a>";
str_ireplace($oldText, $newText,$string);
这只是一个例子。 custom这个词也可以放在字符串的中间或者开头...
谢谢
您可能必须使用 PHP's DOM parser 才能做到这一点。写一个正则表达式来解决它并不适用于所有情况。
A) DOM
我会从 custom
替换为 <span>custom</span>
时,您将创建一个新的 DOM 元素。替换文本内容将不起作用,因为 <span>
将被转义并替换为 <span>
。
所以我会这样做:
使用preg_match_all()和
/\bcustom\b/
等模式来获取文本中找到的项目的所有偏移量:// Search for the word, but delimited by word boundaries to // avoid matching 'custom' in 'customization' or 'customer'. $pattern = '/\b' . preg_quote($word_to_search) . '\b/'; if (preg_match_all($pattern, $child->wholeText, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { var_export($matches); }
将这些以字节为单位的偏移量转换为以字符为单位的偏移量(这是因为 UTF-8 可以有 1 个或 n 个字节的字符):
function char_offset($string, $byte_offset, $encoding = null) { $substr = substr($string, 0, $byte_offset); return mb_strlen($substr, $encoding ?: mb_internal_encoding()); }
使用DOMText::splitText()将文本节点拆分为两个文本节点,偏移量以字符为单位。
使用 DOMDocument::createElement()
创建一个<span>
元素$new_text = 'custom'; // or whatever. $spanElement = $domNode->ownerDocument->createElement('span', $new_text);
- 的第二个文本节点之前插入此跨度元素
更正第二个文本节点以删除开头的
custom
单词。
B) 使用正则表达式
但是如果你的案例总是在 <a>
标签中,那么你可以尝试这样的事情:https://regex101.com/r/ksPqxe/1
正则表达式的解释请看右栏的说明。如果需要,您可以删除 case-insensitive 的 i
标志。使用 s
标志以便 .
也匹配新行。我不得不使用带有 .*?
而不是 .*
的非贪婪搜索。所以最后我使用 U
作为 Ungreedy 标志,然后使用 .*
.
此解决方案无法处理 link 中多个 custom
个单词的情况。但你可能只有一次。如果需要,则使用一个正则表达式获取 link 的文本内容,然后使用第二个正则表达式将 custom
的所有实例替换为 <span>custom</span>
.
<?php
$pattern = '/(<a[^>]*>.*)\bcustom\b(.*<\/a>)/isU';
// Or without the ungreedy flag:
//$pattern = '/(<a[^>]*>.*?)\bcustom\b(.*?<\/a>)/is';
$substitution = '<span>custom</span>';
$inputs = [
"<a href='#' title='Products custom'>Products custom</a>",
'<a href="https://www.customer.com" title="customer" data-type="custom">Custom stuff</a>',
'<a href=\"https://www.customer.com\" title=\"customer"
data-type="custom">Customer stuff</a>',
'<a href="#">customize it!</a>',
];
$results = [];
foreach ($inputs as $input) {
$result = preg_replace($pattern, $substitution, $input);
$results[] = "$input\n$result\n";
}
print implode(str_repeat('-', 80) . "\n", $results);
输出:
<a href='#' title='Products custom'>Products custom</a>
<a href='#' title='Products custom'>Products <span>custom</span></a>
--------------------------------------------------------------------------------
<a href="https://www.customer.com" title="customer" data-type="custom">Custom stuff</a>
<a href="https://www.customer.com" title="customer" data-type="custom"><span>custom</span> stuff</a>
--------------------------------------------------------------------------------
<a href=\"https://www.customer.com\" title=\"customer"
data-type="custom">Customer stuff</a>
<a href=\"https://www.customer.com\" title=\"customer"
data-type="custom">Customer stuff</a>
--------------------------------------------------------------------------------
<a href="#">customize it!</a>
<a href="#">customize it!</a>