合并 PHP 中标签的重复属性
Combining duplicate attributes from a tag in PHP
我需要将字符串 This <span style="font-size: 16px;" style="color: red;">is</span> a test.
转换为 This <span style="font-size: 16px; color: red;">is</span> a test.
也有可能有两个以上的匹配项,或者可能有一个 style
,然后是一个 class
,然后是另一个 style
,然后是 style
s 需要合并。他们不会总是 span
s
不幸的是,Tidy 不是一个选项,因为它在清洁方面比这个项目可以容纳的更过分。
使用 DOM 文档路由将不起作用,因为多个样式属性无效,因此它只获取第一个的内容。
我想用 preg_replace 做到这一点,但事实证明,仅从一个标签中获取匹配项非常困难。
如果它能让事情变得更简单,它们就以嵌套标签开始。我有一个 preg_replace 从那里组合它们并给出这个输出。
我同意上面的评论,最好的解决方案是首先防止这种情况,但回答你的问题:这个函数将组合给定字符串中的所有样式属性。只需确保一次只传递一个标签。标记中有多少其他属性并不重要,顺序也不重要。它将所有样式属性合并到第一个样式值中,然后删除所有其他样式属性:
/**
* @param string $str
* @return string
*/
function combineStyles($str)
{
$found = preg_match_all("/style=\"([^\"]+)\"/", $str, $matches);
if ($found)
{
$combined = 'style="' . implode(';', $matches[1]) . '"';
$patterns = $matches[0];
$replace = array_pad(array($combined), count($matches[0]), '');
$str = str_replace($patterns, $replace, $str);
}
return $str;
}
等等,我刚刚意识到它不适用于 style="" id="" style=""
。
<?php
$str = 'This <span style="font-size: 16px" style="color: red;">is</span> a test. This <span style="font-size: 16px;" style="color: red;">is</span> a test.';
while (preg_match('/"\s+style="/', $str, $matches))
{
$pos = strpos($str, $matches[0]);
$prev = substr($str, 0, $pos);
if (substr(trim($prev), -1) != ";")
$prev .= ";";
$str = $prev.substr($str, $pos+strlen($matches[0]));
}
?>
在 Visual Studio 2012 年的快速替换中使用 .Net 正则表达式,这个表达式对我有用:
Find:
style\s*=\s*(?<q2>['"])(?<w1>(?:(?!\k<q2>).)*?);?\k<q2>\s*(?<c>[^<>]*)\s*style\s*=\s*(?<q2>['"])(?<w2>(?:(?!\k<q2>).)*?);?\k<q2>
Replace:
style="${w1};${w2};" ${c}
备注:
1.这一次只会合并两个style
属性。如果单个标签中有多个,则需要多次运行。
2.两个样式属性之间的任何内容都将放在第一个样式属性之后(这是合并后的样式属性将放置的位置)
说明
Find:
style # match a style attribute
\s* # match any optional white space
= # match equals sign
\* # match any optional white space
(?<q2>['"]) # match either a single or double quote and stored in named capture 'q'
(?<w1> # start capture of first style attribute's content
(?: # start non-capturing match
(?!\k<q2>) # negative look-ahead to prevent matching on this attribute's quote
.)*? # end non-capturing match with minimal, 0-many quantifier
) # end capture of first style attribute's content
;? # place trailing semi-colon (if present) outside the capture
\k<q2> # match closing quote
\s* # match white space
(?<c>[^<>]*) # capture content between style attributes
\s* # match white space
... # repeat the above for a second style attribute
# except that the second style's capture is named 'w2'
Replacement:
style=" # start merged style attribute
${w1}; # place first style attribute's content
${w2}; # place second style attribute's content
" # finish merge style attribute
${c} # restore any content found between the two style attributes
我需要将字符串 This <span style="font-size: 16px;" style="color: red;">is</span> a test.
转换为 This <span style="font-size: 16px; color: red;">is</span> a test.
也有可能有两个以上的匹配项,或者可能有一个 style
,然后是一个 class
,然后是另一个 style
,然后是 style
s 需要合并。他们不会总是 span
s
不幸的是,Tidy 不是一个选项,因为它在清洁方面比这个项目可以容纳的更过分。
使用 DOM 文档路由将不起作用,因为多个样式属性无效,因此它只获取第一个的内容。
我想用 preg_replace 做到这一点,但事实证明,仅从一个标签中获取匹配项非常困难。
如果它能让事情变得更简单,它们就以嵌套标签开始。我有一个 preg_replace 从那里组合它们并给出这个输出。
我同意上面的评论,最好的解决方案是首先防止这种情况,但回答你的问题:这个函数将组合给定字符串中的所有样式属性。只需确保一次只传递一个标签。标记中有多少其他属性并不重要,顺序也不重要。它将所有样式属性合并到第一个样式值中,然后删除所有其他样式属性:
/**
* @param string $str
* @return string
*/
function combineStyles($str)
{
$found = preg_match_all("/style=\"([^\"]+)\"/", $str, $matches);
if ($found)
{
$combined = 'style="' . implode(';', $matches[1]) . '"';
$patterns = $matches[0];
$replace = array_pad(array($combined), count($matches[0]), '');
$str = str_replace($patterns, $replace, $str);
}
return $str;
}
等等,我刚刚意识到它不适用于 style="" id="" style=""
。
<?php
$str = 'This <span style="font-size: 16px" style="color: red;">is</span> a test. This <span style="font-size: 16px;" style="color: red;">is</span> a test.';
while (preg_match('/"\s+style="/', $str, $matches))
{
$pos = strpos($str, $matches[0]);
$prev = substr($str, 0, $pos);
if (substr(trim($prev), -1) != ";")
$prev .= ";";
$str = $prev.substr($str, $pos+strlen($matches[0]));
}
?>
在 Visual Studio 2012 年的快速替换中使用 .Net 正则表达式,这个表达式对我有用:
Find:
style\s*=\s*(?<q2>['"])(?<w1>(?:(?!\k<q2>).)*?);?\k<q2>\s*(?<c>[^<>]*)\s*style\s*=\s*(?<q2>['"])(?<w2>(?:(?!\k<q2>).)*?);?\k<q2>
Replace:
style="${w1};${w2};" ${c}
备注:
1.这一次只会合并两个style
属性。如果单个标签中有多个,则需要多次运行。
2.两个样式属性之间的任何内容都将放在第一个样式属性之后(这是合并后的样式属性将放置的位置)
说明
Find:
style # match a style attribute
\s* # match any optional white space
= # match equals sign
\* # match any optional white space
(?<q2>['"]) # match either a single or double quote and stored in named capture 'q'
(?<w1> # start capture of first style attribute's content
(?: # start non-capturing match
(?!\k<q2>) # negative look-ahead to prevent matching on this attribute's quote
.)*? # end non-capturing match with minimal, 0-many quantifier
) # end capture of first style attribute's content
;? # place trailing semi-colon (if present) outside the capture
\k<q2> # match closing quote
\s* # match white space
(?<c>[^<>]*) # capture content between style attributes
\s* # match white space
... # repeat the above for a second style attribute
# except that the second style's capture is named 'w2'
Replacement:
style=" # start merged style attribute
${w1}; # place first style attribute's content
${w2}; # place second style attribute's content
" # finish merge style attribute
${c} # restore any content found between the two style attributes