匹配所有元素与背景颜色

时间:2021-10-31 21:07:28

Here's the issue - in a TinyMCE I'm working with it's adding a background-color on a span wrapper instead of the parent element. I'm trying to search the content string and grab the span styles to put it on the parent element. I have HTML like this:

这是问题 - 在TinyMCE中我正在使用它在跨度包装器而不是父元素上添加背景颜色。我正在尝试搜索内容字符串并获取span样式以将其放在父元素上。我有像这样的HTML:

<h3><span style="background-color: #000000;">Hello World!</span></h3>

So I'm trying to match any span with a background or background-color and put that as a style onto its parent. I'm trying to work with DOMDocument but I'm not too familiar with it:

所以我试图将任何跨度与背景或背景颜色匹配,并将其作为样式放在其父级上。我正在尝试使用DOMDocument,但我不太熟悉它:

$html       = '<h3><span style="background-color: #000000;">Hello World!</span></h3>';
$htmlDOM    = new DOMDocument();
$htmlDOM->loadHTML( $html );
$xpath      = new DOMXPath( $htmlDOM );
$headers = $xpath->query( '//h1//span|//h2//span|//h3//span|//h4//span|//h5//span|//h6//span' );

foreach( $headers as $index => $element ) {
    print_r( $element );    // The Header Element

    if( $element->attributes->length ) {
        foreach( $element->attributes as $asdf => $attr ) {
            print_r( $attr );   // The Span Attributes ( style )
        }
    }
}

I get the actual style attribute with the above but I don't know how to assign it to the parent. I'm not sure if this is faster than preg_match() but I'm not familiar enough with regex. Any help / suggestions or tips would be appreciated!

我得到了上面的实际样式属性,但我不知道如何将它分配给父。我不确定这是否比preg_match()快,但我对正则表达式不够熟悉。任何帮助/建议或提示将不胜感激!

3 个解决方案

#1


2  

$html       = '<h3><span style="background-color: #000000;">Hello World!</span></h3>';
$htmlDOM    = new DOMDocument();
$htmlDOM->loadHTML( $html );
$xpath      = new DOMXPath( $htmlDOM );
// Find `h*` having child `span` with `style` attribute    
$headers = $xpath->query( '//*[contains("h1|h2|h3|h4|h5|h6", name())  and span[@style]]');

foreach( $headers as $element) {
    // Find `span` element
    $span = $xpath->query('./span', $element)->item(0);
    // Move all attributes from `span` to `h*
    foreach($span->attributes as $attr)
       $element->setAttribute($attr->name, $attr->nodeValue);
    // Save value of `span`
    $value = $element->nodeValue;
    // Remove `span` 
    $span->parentNode->removeChild($span);
    // Set former `span` value as `h*` value
    $element->nodeValue = $value;
}

echo $htmlDOM->saveHTML();

demo

#2


0  

A dom solution would be better. But if you want to use a regex solution, you could use:

一个dom解决方案会更好。但是如果你想使用正则表达式解决方案,你可以使用:

$html     = '<h3><span style="background-color: #000000;">Hello World!</span></h3>';
$html_new = preg_replace("@(<h\d[^>]*)(>)(\s*<span[^<>]+)(style\s*=\s*["'][^"']*["'])[^>]*>([^<>]+)</span>@", "$1 $4$2$5", $html);

It will only work on h1 etc. elements, and if the span element will follow directely and has no child elements.

它只适用于h1等元素,如果span元素将直接跟随并且没有子元素。

#3


0  

Thanks to /u/splash58's answer it pushed me in the right direction:

感谢/ u / splash58的回答,它促使我朝着正确的方向前进:

$html       = '<h3><span style="background-color: #000000;">Hello World!</span></h3>';
$htmlDOM    = new DOMDocument();
$htmlDOM->loadHTML( $html );
$xpath      = new DOMXPath( $htmlDOM );
$elements   = $xpath->query( '//h1//span|//h2//span|//h3//span|//h4//span|//h5//span|//h6//span' );

if( $elements->length ) {
    foreach( $elements as $span ) {
        $span_style = $span->getAttribute( 'style' );

        if( false !== strpos( $span_style, 'background' ) ) {
            $parent_style   = $span->parentNode->getAttribute( 'style' );
            $parent_style   = rtrim( $parent_style, ';' );
            $span_style     = rtrim( $span_style, ';' );

            $new_style      = "{$parent_style}; {$span_style};";
            $parent_style   = $span->parentNode->setAttribute( 'style', $new_style );
            $span->parentNode->nodeValue = $span->nodeValue;
        }
    }
}

echo $htmlDOM->saveHTML();

One thing I'm not certain on is why the span gets removed when I didn't specifically remove it. It seems to happen after I assign the spans nodeValue to the parent. If anyone has an idea on why this might be or clarification please comment below and let me know!

我不确定的一件事是,当我没有特别删除它时,为什么跨度被删除。这似乎发生在我将跨度nodeValue分配给父节点之后。如果有人知道为什么会这样或澄清,请在下面评论并告诉我!

#1


2  

$html       = '<h3><span style="background-color: #000000;">Hello World!</span></h3>';
$htmlDOM    = new DOMDocument();
$htmlDOM->loadHTML( $html );
$xpath      = new DOMXPath( $htmlDOM );
// Find `h*` having child `span` with `style` attribute    
$headers = $xpath->query( '//*[contains("h1|h2|h3|h4|h5|h6", name())  and span[@style]]');

foreach( $headers as $element) {
    // Find `span` element
    $span = $xpath->query('./span', $element)->item(0);
    // Move all attributes from `span` to `h*
    foreach($span->attributes as $attr)
       $element->setAttribute($attr->name, $attr->nodeValue);
    // Save value of `span`
    $value = $element->nodeValue;
    // Remove `span` 
    $span->parentNode->removeChild($span);
    // Set former `span` value as `h*` value
    $element->nodeValue = $value;
}

echo $htmlDOM->saveHTML();

demo

#2


0  

A dom solution would be better. But if you want to use a regex solution, you could use:

一个dom解决方案会更好。但是如果你想使用正则表达式解决方案,你可以使用:

$html     = '<h3><span style="background-color: #000000;">Hello World!</span></h3>';
$html_new = preg_replace("@(<h\d[^>]*)(>)(\s*<span[^<>]+)(style\s*=\s*["'][^"']*["'])[^>]*>([^<>]+)</span>@", "$1 $4$2$5", $html);

It will only work on h1 etc. elements, and if the span element will follow directely and has no child elements.

它只适用于h1等元素,如果span元素将直接跟随并且没有子元素。

#3


0  

Thanks to /u/splash58's answer it pushed me in the right direction:

感谢/ u / splash58的回答,它促使我朝着正确的方向前进:

$html       = '<h3><span style="background-color: #000000;">Hello World!</span></h3>';
$htmlDOM    = new DOMDocument();
$htmlDOM->loadHTML( $html );
$xpath      = new DOMXPath( $htmlDOM );
$elements   = $xpath->query( '//h1//span|//h2//span|//h3//span|//h4//span|//h5//span|//h6//span' );

if( $elements->length ) {
    foreach( $elements as $span ) {
        $span_style = $span->getAttribute( 'style' );

        if( false !== strpos( $span_style, 'background' ) ) {
            $parent_style   = $span->parentNode->getAttribute( 'style' );
            $parent_style   = rtrim( $parent_style, ';' );
            $span_style     = rtrim( $span_style, ';' );

            $new_style      = "{$parent_style}; {$span_style};";
            $parent_style   = $span->parentNode->setAttribute( 'style', $new_style );
            $span->parentNode->nodeValue = $span->nodeValue;
        }
    }
}

echo $htmlDOM->saveHTML();

One thing I'm not certain on is why the span gets removed when I didn't specifically remove it. It seems to happen after I assign the spans nodeValue to the parent. If anyone has an idea on why this might be or clarification please comment below and let me know!

我不确定的一件事是,当我没有特别删除它时,为什么跨度被删除。这似乎发生在我将跨度nodeValue分配给父节点之后。如果有人知道为什么会这样或澄清,请在下面评论并告诉我!