DOMDocument - 如何替换嵌套元素

Gio*_*ona 1 php domdocument domxpath

我有这个html片段:

<font color="#ff0000">Lorem <font size="4">ipsum dolor</font> sit amet</font>
Run Code Online (Sandbox Code Playgroud)

我想使用DOMDocument font用a 替换每个标记span.这是我的功能atm:

$fonts = $xPath->query('//font');
foreach($fonts as $font){
    $style = '';
    $newFont = $dom->createElement('span',$font->nodeValue);
    if($font->hasAttribute('size')){
        $size = $font->getAttribute('size');
        $style.='font-size:'.round($size/2,1).'em; ';
    }
    if($font->hasAttribute('color')){
        $style.='color:'.$font->getAttribute('color').'; ';
    }
    if($style!='') $newFont->setAttribute('style',$style);
    $font->parentNode->replaceChild($newFont,$font);
}
Run Code Online (Sandbox Code Playgroud)

我期待这个输出:

<span style="color:#ff0000; ">Lorem <span style="font-size:2em;">ipsum etc..
Run Code Online (Sandbox Code Playgroud)

但我得到:

<span style="color:#ff0000; ">Lorem ipsum dolor sit amet</span>
Run Code Online (Sandbox Code Playgroud)

为什么?


我想这$font->parentNode->replaceChild($newFont,$font);是因为以某种方式用它的文本值替换外部跨度......或者这个查询可能$xPath->query('//font')是错误的.我很喜欢经验丰富的建议......谢谢

Bab*_*aba 8

介绍

从以下对话中

rekire

你为什么不简单地使用正则表达式? -

GionaF

rekire我已经做了很长时间了,但我正在尝试切换到DOMDocument/html5lib ... codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html`

我完全同意这就是为什么我相信这不是一个工作的两个DomDocumentRegular Expresstion,因为你面对的问题depreciated HTML Tags是,在HTML 5不再支持

意义

这意味着font您可能还必须替换这个问题

  • 缩写
  • 小程序
  • BASEFONT
  • 中央
  • DIR
  • 框架
  • 无框架
  • 小号
  • 罢工
  • TT
  • XMP

使用整洁

我会推荐Tidy,它的设计是为了让你不必做你将要做的事情

FORM PHP DOC

Tidy是Tidy HTML 清理修复实用程序的绑定,它不仅允许您清理和操作HTML文档,还可以遍历文档树.

$html = '<font color="#ff0000">Lorem <font size="4">ipsum dolor</font> sit amet</font>';
$config = array(
        'indent' => true,
        'show-body-only' => false,
        'clean' => true,
        'output-xhtml' => true,
        'preserve-entities' => true);

$tidy = new tidy();
echo $tidy->repairString($html, $config, 'UTF8');
Run Code Online (Sandbox Code Playgroud)

产量

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <style type="text/css">
            /*<![CDATA[*/
            span.c2 {
                color: #FF0000
            }
            span.c1 {
                font-size: 120%
            }
            /*]]>*/
        </style>
    </head>
    <body><span class="c2">Lorem <span class="c1">ipsum dolor</span> sit amet</span>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

有关示例,另请参阅通过删除额外/冗余格式标记清除HTML

Better Sill:HTMLPurifier

您可以使用HTMLPurifier,它也使用Tidy来清理HTML,您只需要设置TidyLevel

HTML Purifier是一个用PHP编写的符合标准的HTML过滤器库.HTML Purifier不仅会删除所有恶意代码(更好地称为XSS),并且具有经过全面审核,安全且宽松的白名单,还可以确保您的文档符合标准,只有通过全面了解W3C规范才能实现这些目标

require_once 'htmlpurifier-4.4.0/library/HTMLPurifier.auto.php';

$html = '<font color="#ff0000">Lorem <font size="4">ipsum dolor</font> sit amet</font>';
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.TidyLevel', 'heavy'); 
$purifier = new HTMLPurifier($config);
$clean = $purifier->purify($html);

var_dump($clean);
Run Code Online (Sandbox Code Playgroud)

产量

string '<span style="color:#ff0000;">Lorem <span style="font-size:large;">ipsum dolor</span> sit amet</span>' (length=100)
Run Code Online (Sandbox Code Playgroud)

我想要DOMDocument

如果你想要的只是dom并且你不关心我的所有解释那么你可以使用

$html = '<font color="#ff0000">Lorem <font size="4">ipsum dolor</font> sit amet</font>';
$dom = new DOMDocument();
$dom->loadHTML($html);
$nodes = iterator_to_array($dom->getElementsByTagName('font'));
foreach ( $nodes as $font ) {
    $css = array();
    $font->hasAttribute('size') and $css[] = 'font-size:' . round($font->getAttribute('size') / 2, 1) . 'em;';
    $font->hasAttribute('color') and $css[]  = 'color:' . $font->getAttribute('color') . ';';
    $span = $dom->createElement('span');
    $children = array();
    foreach ( $font->childNodes as $child )
        $children[] = $child;
    foreach ( $children as $child )
        $span->appendChild($child);
    $span->setAttribute('style', implode('; ', $css));
    $font->parentNode->replaceChild($span, $font);
}
echo "<pre>";
$dom->formatOutput = true;
print(htmlentities($dom->saveXML()));
Run Code Online (Sandbox Code Playgroud)