如何替换html标签内的值?

时间:2015-02-28 20:38:00

标签: php html regex dom preg-replace

我想用$ tagsReplace数组中定义的内容替换元素内容,但是preg_replace有问题,我当前的颂歌:

$tagsReplace = array(
    'header' => 'header',
    'tag1' => 'this is tag1',
    'tag2' => 'this is tag2',
    'tag3' => 'this is tag3',
    'footer' => 'footer',
); 

$content = '
<!DOCTYPE html>
<hthml>
<header data-edit="true" data-tag-id="header"></header>
<div data-edit="true" data-tag-id="tag1"></div>
<div data-edit="true" data-tag-id="tag2"></div>
<div data-edit="true" data-tag-id="tag3"></div>
<footer data-edit="true" data-tag-id="footer"></footer>
</html>
';

$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($content);
$xpath = new DomXpath($dom);

foreach ($xpath->query('//*[@data-edit="true"]') as $rowNode) { 
    $tagID = $rowNode->getAttribute('data-tag-id');
    $content = preg_replace('/(<div.*?data-edit="true"[^>]*>)(.*?)(<\/div>)/i', '$1'. $tagsReplace[$tagID] . '$3', $content);
}
echo $content;

我想要的是得到这样的输出:

<!DOCTYPE html>
<hthml>
<header data-edit="true" data-tag-id="header">header</header>
<div data-edit="true" data-tag-id="tag1">this is tag1</div>
<div data-edit="true" data-tag-id="tag2">this is tag2</div>
<div data-edit="true" data-tag-id="tag3">this is tag3</div>
<footer data-edit="true" data-tag-id="footer">footer</footer>
</html>

当前输出为:

 <!DOCTYPE html>
<hthml>
<header data-edit="true" data-tag-id="header"></header>
<div data-edit="true" data-tag-id="tag1">footer</div>
<div data-edit="true" data-tag-id="tag2">footer</div>
<div data-edit="true" data-tag-id="tag3">footer</div>
<footer data-edit="true" data-tag-id="footer"></footer>
</html>

所有包含属性data-edit =&#34; true&#34;和data-tag-id必须将其中的内容替换为tagid值,该值在arra $ tagsReplace中定义。

6 个答案:

答案 0 :(得分:2)

要获得您想要的结果,您可以遍历替换数组并在同一XPath查询中搜索data-edit = truedata-tag-id = <key>,然后替换节点值。这样您根本不必使用preg_replace

$content = '
<!DOCTYPE html>
<html>
<header data-edit="true" data-tag-id="header"></header>
<div data-edit="true" data-tag-id="tag1"></div>
<div data-edit="true" data-tag-id="tag2"></div>
<div data-edit="true" data-tag-id="tag3"></div>
<footer data-edit="true" data-tag-id="footer"></footer>
</html>
';

$tagsReplace = array(
    'header' => 'header',
    'tag1'   => 'this is tag1',
    'tag2'   => 'this is tag2',
    'tag3'   => 'this is tag3',
    'footer' => 'footer',
);

$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($content);
$xpath = new DomXpath($dom);

foreach ($tagsReplace as $key => $value) {
    $nodes = $xpath->query(
        '//*[@data-edit="true" and @data-tag-id="' . $key . '"]'
    );

    if ($nodes->length) {
        $nodes->item(0)->nodeValue = $value;
    }
}

$dom->formatOutput = true;
echo $dom->saveHTML();

输出:

<!DOCTYPE html>
<html><body>
<header data-edit="true" data-tag-id="header">header</header>
<div data-edit="true" data-tag-id="tag1">this is tag1</div>
<div data-edit="true" data-tag-id="tag2">this is tag2</div>
<div data-edit="true" data-tag-id="tag3">this is tag3</div>
<footer data-edit="true" data-tag-id="footer">footer</footer>
</body></html>

答案 1 :(得分:2)

试试这个,它接受任何类型的标签

$tagsReplace = array(
    'header' => 'header',
    'tag1' => 'this is tag1',
    'tag2' => 'this is tag2',
    'tag3' => 'this is tag3',
    'footer' => 'footer',
); 

$content = '
<!DOCTYPE html>
<html>
<header data-edit="true" data-tag-id="header"></header>
<div data-edit="true" data-tag-id="tag1"></div>
<div data-edit="true" data-tag-id="tag2"></div>
<div data-edit="true" data-tag-id="tag3"></div>
<footer data-edit="true" data-tag-id="footer"></footer>
</html>
';

$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($content);
$xpath = new DomXpath($dom);

foreach ($xpath->query('//*[@data-edit="true"]') as $rowNode) {
    $tagID = $rowNode->getAttribute('data-tag-id');
    $content = preg_replace('/(<(.*?) [^>]*?data-tag-id="'.$tagID.'"[^>]*>)(.*?)(<\/\2>)/i', '$1'. $tagsReplace[$tagID] . '$4', $content);
}
echo $content;

答案 2 :(得分:2)

foreach ($xpath->query('//*[@data-edit="true"]') as $rowNode) {
    $rowNode->nodeValue = $tagsReplace[$rowNode->getAttribute('data-tag-id')];
}
echo $dom->saveHTML();

答案 3 :(得分:2)

因为您正在指定 你的preg_match模式中的 div 我们知道第一个元素以标题开头,因此无法匹配 所以只需更换&#34; div&#34;在preg_match模式的开头用(。*?)匹配标题甚至其他单词。 这个:

$ content = preg_replace(&#39; /(&lt; div ?data-edit =&#34; true&#34; [^&gt;] &gt;)(。*?)(&lt; / div&gt;)/ i&#39;,&#39; $ 1&#39;。$ tagsReplace [$ tagID]。&#39; $ 3&#39;,$ content );

变为:

$ content = preg_replace(&#39; /(&lt; (。*?) data-edit =&#34; true&#34; [^&gt;] &gt; )(。?)(&lt; / div&gt;)/ i&#39;,&#39; $ 1&#39;。$ tagsReplace [$ tagID]。&#39; $ 3&#39;,$内容);

另一种选择是你可以使用 preg_replace_callback(模式,功能,主题)来做你想要的神奇的事情,这是一个对我有用的解决方案:

$content = '
<!DOCTYPE html>
<hthml>
<header data-edit="true" data-tag-id="header"></header>
<div data-edit="true" data-tag-id="tag1"></div>
<div data-edit="true" data-tag-id="tag2"></div>
<div data-edit="true" data-tag-id="tag3"></div>
<footer data-edit="true" data-tag-id="footer"></footer>
</html>
';

$pattern = '/<(.+) data-edit="true" data-tag-id="(.*)"(.*?)>(.*?)<\/(.+)>/';
$another = preg_replace_callback($pattern, function($matches){
    $tagsReplace = array(
        'header' => 'header1',
        'tag1' => 'this is tag1',
        'tag2' => 'this is tag2',
        'tag3' => 'this is tag3',
        'footer' => 'footer',
    ); 
    return '<'.$matches[1].' data-edit="true" data-tag-id="'.$matches[2].'"'.$matches[3].'>'.$tagsReplace[$matches[2]].'<\/'.$matches[5].'>/';
}, $content);
# before the replacement 
print_r($content);
echo '\n';
// another holds the content after replacement 
print_r($another);

答案 4 :(得分:1)

你不能总是用同一个赞助人替换,因为你有3个不同的标签。

看看这段代码:

<?php

$tagsReplace = array(
    'header' => 'header',
    'tag1' => 'this is tag1',
    'tag2' => 'this is tag2',
    'tag3' => 'this is tag3',
    'footer' => 'footer',
); 

$content = '
<!DOCTYPE html>
<html>
<header data-edit="true" data-tag-id="header"></header>
<div data-edit="true" data-tag-id="tag1"></div>
<div data-edit="true" data-tag-id="tag2"></div>
<div data-edit="true" data-tag-id="tag3"></div>
<footer data-edit="true" data-tag-id="footer"></footer>
</html>
';

$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($content);
$xpath = new DomXpath($dom);

$html = explode("\n", trim($content));
$i = 2;

foreach ($xpath->query('//*[@data-edit="true"]') as $rowNode) { 
    $tagID = $rowNode->getAttribute('data-tag-id');

    switch ($rowNode->nodeName) {
        case 'header':
        $html[$i] = preg_replace('/(<header.*?data-edit="true"[^>]*>)(.*?)(<\/header>)/i', '$1'. $tagsReplace[$tagID] . '$3', $html[$i]);
        break;

        case 'div':
        $html[$i] = preg_replace('/(<div.*?data-edit="true"[^>]*>)(.*?)(<\/div>)/i', '$1'. $tagsReplace[$tagID] . '$3', $html[$i]);
        break;  

        case 'footer':
        $html[$i] = preg_replace('/(<footer.*?data-edit="true"[^>]*>)(.*?)(<\/footer>)/i', '$1'. $tagsReplace[$tagID] . '$3', $html[$i]);
        break;  
    }   
    $i++;
}

$content = implode("\n", $html);

echo $content;

?>

答案 5 :(得分:1)

不要使用RegEx来解析/更改HTML或XML。您已经使用了DOM,那么为什么不使用它来更改文档呢?

$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($content);
$xpath = new DOMXPath($dom);

foreach ($xpath->evaluate('//*[@data-edit="true"]') as $rowNode) {
  // read id attribute 
  $tagId = $rowNode->getAttribute('data-tag-id');
  // remove all child nodes
  $rowNode->nodeValue = '';
  // if here is a new content available
  if (isset($tagsReplace[$tagId])) {
      // create a text node and append it
      $rowNode->appendChild(
         $dom->createTextNode($tagsReplace[$tagId])
      );
  }
}
echo $dom->saveHtml();

输出(格式化):

<!DOCTYPE html>
<html>
  <body>
    <header data-edit="true" data-tag-id="header">header</header>
    <div data-edit="true" data-tag-id="tag1">this is tag1</div>
    <div data-edit="true" data-tag-id="tag2">this is tag2</div>
    <div data-edit="true" data-tag-id="tag3">this is tag3</div>
    <footer data-edit="true" data-tag-id="footer">footer</footer>
  </body>
</html>

警告!:您的HTML看起来像HTML5,并且与PHP DOM实现不完全兼容。您可能需要library将HTML5作为XHTML导入/导出到DOMDocument。