将DOM元素包装在PHP中的另一个DOM元素中 [英] Wrap DOM element in another DOM element in PHP

查看:117
本文介绍了将DOM元素包装在PHP中的另一个DOM元素中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最初使用正则表达式提出了一个这样的问题,但是建议使用PHP DOM库,这是优越的,但我仍然坚持。

I originally asked a question along these lines using Regex but was recommended to use the PHP DOM library instead... which is superior, but I am still stuck.

基本上,我想将< a> 的内容包裹在< span> 中,如果是尚未包裹在< span> 中。

Basically, I want to wrap the contents of an <a> in a <span> if it is not already wrapped in <span>.

<?php
$input = <<<EOT
<html><head></head>
<body bgcolor="#393a36">
    <a href="#"><span style="color:#ffffff;">Link 1</span></a>
    <a href="#">Link 2</a>
    <a href="#"><img src="mypic.gif" />Image Link</a>
    <a href="#"><u>Underlined Link</u></a>
</body>
</html>
EOT;


$doc = new DOMDocument();
$doc->loadHTML($input);
$tags = $doc->getElementsByTagName('a');
foreach ($tags as $tag) {
    $spancount = $tag->getElementsByTagName("span")->length;
    if($spancount == 0){
        $content = nodeContent($tag);
        $element = $doc->createElement('span');
        $element->setAttribute('style','color:#ffffff;');
        $frag = $doc->createDocumentFragment();
        $frag->appendXML($content);
        $element->appendChild($frag);   
        $tag->nodeValue = ""; //clear node
        $tag->appendChild($element);
    }
}
echo $doc->saveHTML();

function nodeContent($n, $outer=false) { 
    $d = new DOMDocument('1.0'); 
    $d->formatOutput = true;
    $b = $d->importNode($n->cloneNode(true),true); 
    $d->appendChild($b);
    $h = $d->saveHTML(); 
    // remove outter tags 
    if (!$outer) $h = substr($h,strpos($h,'>')+1,-(strlen($n->nodeName)+4)); 
    return $h; 
} 

提供此输出:


PHP警告:DOMDocumentFragment :: appendXML():实体:行1:解析器错误:/ private / var / folders / 78 / 78vHGigZHcuFeXB1KKJSb中的标签img第1行中的数据提前结束+ +++ TI / -Tmp- / untitled_3xd..php第24行

PHP警告:DOMDocumentFragment :: appendXML():Image Link in / private / var / folders / 78 / 78vHGigZHcuFeXB1KKJSb ++++ TI / -Tmp- / untitled_3xd..php第24行
PHP警告:DOMDocumentFragment :: appendXML():^ in / private / var / folders / 78 / 78vHGigZHcuFeXB1KKJSb ++++ TI / -Tmp- / untitled_3xd ..php on line 24
PHP警告:DOMNode :: appendChild():文档片段为空,在/private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++第25行

PHP Warning: DOMDocumentFragment::appendXML(): Entity: line 1: parser error : Premature end of data in tag img line 1 in /private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php on line 24
PHP Warning: DOMDocumentFragment::appendXML(): Image Link in /private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php on line 24 PHP Warning: DOMDocumentFragment::appendXML(): ^ in /private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php on line 24 PHP Warning: DOMNode::appendChild(): Document Fragment is empty in /private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php on line 25



<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>  
<head></head>  
<body bgcolor="#393a36">  
    <a href="#"><span style="color:#ffffff;">Link 1</span></a>  
    <a href="#"><span style="color:#ffffff;">Link 2</span></a>  
    <a href="#"><span style="color:#ffffff;"></span></a>  
    <a href="#"><span style="color:#ffffff;"><u>Underlined Link</u></span></a>  
</body>  
</html>

这主要有效,除了它真的很挑剔,你可以看到它死了,如果这里是 img (或类似的)标签在 a href 中。

This mostly works, except that it is really picky, and as you can see it dies if here is an img (or similar) tag inside the a href.

使这项工作最好的方法是什么?

What is the best way to make this work. I've been banging my head against for an embarrassing long time now.

编辑

根据下面的反馈,这里是修改后的代码和输出。请注意,由于某些原因, img 标记之前的文本未被包装。任何想法?

Based on feedback below, here is the revised code and output. Note that the text preceding the img tag isn't being wrapped for some reason. Any Ideas?

$doc = new DOMDocument();
$doc->loadHTML($input);
$tags = $doc->getElementsByTagName('a');
foreach ($tags as $tag) {
    $spancount = $tag->getElementsByTagName("span")->length;
    if($spancount == 0){
    $element = $doc->createElement('span');
    $element->setAttribute('style','color:#ffffff;');
    foreach ($tag->childNodes as $child) {
        $tag->removeChild($child);
        $element->appendChild($child);
    }
    $tag->appendChild($element);

    }
}
echo $doc->saveHTML();

输出:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head></head>
<body bgcolor="#393a36">
    <a href="#"><span style="color:#ffffff;">Link 1</span></a>
    <a href="#"><span style="color:#ffffff;">Link 2</span></a>
    <a href="#">Image Link<span style="color:#ffffff;"><img src="mypic.gif"></span></a>
    <a href="#"><span style="color:#ffffff;"><u>Underlined Link</u></span></a>
</body>
</html>


推荐答案

为什么要重新创建节点?为什么不更换节点? (如果我明白你想做什么)...

Why bother with re-creating the node? Why not just replace the node? (If I understand what you're trying to do)...

if($spancount == 0){
    $element = $doc->createElement('span');
    $element->setAttribute('style','color:#ffffff;');
    $tag->parentNode->replaceChild($element, $tag);
    $element->apendChild($tag);
}

修改糟糕,看起来你是尝试将所有内容都包含在 $ tag 的范围内...尝试这样做:

Edit Whoops, it looks like you're trying to wrap everything under $tag in the span... Try this instead:

if($spancount == 0){
    $element = $doc->createElement('span');
    $element->setAttribute('style','color:#ffffff;');
    foreach ($tag->childNodes as $child) {
        $tag->removeChild($child);
        $element->appendChild($child);
    }
    $tag->appendChild($child);
}

Edit2 根据您的结果,它看起来像由于节点删除,foreach没有完成...尝试用以下替换foreach:

Edit2 Based on your results, it looks like that foreach is not completing because of the node removal... Try replacing the foreach with this:

while ($tag->childNodes->length > 0) {
    $child = $tag->childNodes->item(0);
    $tag->removeChild($child);
    $element->appendChild($child);
}

这篇关于将DOM元素包装在PHP中的另一个DOM元素中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆