在PHP中组合标记的重复属性

时间:2015-07-23 15:41:18

标签: php html html-parsing

我需要将字符串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,然后是另一个stylestyle s需要合并。它们并不总是span s

不幸的是,Tidy不是一个选项,因为它的清洁工作比这个项目更容易承受。

由于多个样式属性无效,因此转到DOM文档路由将不起作用,因此它只获取第一个样式的内容。

我想用preg_replace来做,但是从一个标签中获取匹配证明是非常困难的。

如果它使事情变得更容易,它们就像嵌套标签一样开始。我有一个preg_replace,它从那里组合它们并给出这个输出。

3 个答案:

答案 0 :(得分:0)

我同意上面的评论,最好的解决方案是首先防止这种情况,但回答你的问题:这个函数将结合给定字符串中的所有样式属性。只需确保一次只传递一个标签。标签中有多少其他属性并不重要,订单也不重要。它会将所有样式属性组合到第一个样式值中,然后删除所有其他样式属性:

/**
 * @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;
}

答案 1 :(得分:0)

等等,我刚刚意识到它不能与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]));
}
?>

答案 2 :(得分: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