Php DOMDocument-如何替换嵌套元素
我有一个html片段:Php DOMDocument-如何替换嵌套元素,php,domdocument,domxpath,Php,Domdocument,Domxpath,我有一个html片段: <font color="#ff0000">Lorem <font size="4">ipsum dolor</font> sit amet</font> 我期望这个输出: <span style="color:#ff0000; ">Lorem <span style="font-size:2em;">ipsum etc.. Lorem ipsum等。。 但我得到: <span style
<font color="#ff0000">Lorem <font size="4">ipsum dolor</font> sit amet</font>
我期望这个输出:
<span style="color:#ff0000; ">Lorem <span style="font-size:2em;">ipsum etc..
Lorem ipsum等。。
但我得到:
<span style="color:#ff0000; ">Lorem ipsum dolor sit amet</span>
Lorem ipsum dolor sit amet
为什么?
我猜这是因为
$font->parentNode->replaceChild($newFont,$font)代码>正在以某种方式将外部跨距仅替换为其文本值。。。或者这个查询$xPath->query('//font')
是错误的。我喜欢有经验的建议。。。谢谢看来您的代码示例遇到了几个不同的问题
查询结果包含正在更改的项
$node->nodValue不包含子节点
发现从foreach更改为while,并多次运行查询解决了在更改树中查找节点的问题
$fonts = $xPath->query('//font');
while ($fonts->length > 0) {
$font = $fonts->item(0);
// Get bits of data before touching the tree
$style = '';
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') . '; ';
}
// Create the new node
$newFont = $dom->createElement('span');
if(!empty($style)) {
$newFont->setAttribute('style', $style);
}
// Copy all children into a basic array to avoid an iterator
// on a changing tree
$children = iterator_to_array($font->childNodes);
foreach ($children as $child) {
// This has a side effect of removing the child from its old
// location, which changes the tree
$newFont->appendChild($child);
}
// Replace the parent's child, which changes the tree
$font->parentNode->replaceChild($newFont, $font);
// query again on the new tree
$fonts = $xPath->query('//font');
}
您的代码示例似乎遇到了几个不同的问题
查询结果包含正在更改的项
$node->nodValue不包含子节点
发现从foreach更改为while,并多次运行查询解决了在更改树中查找节点的问题
$fonts = $xPath->query('//font');
while ($fonts->length > 0) {
$font = $fonts->item(0);
// Get bits of data before touching the tree
$style = '';
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') . '; ';
}
// Create the new node
$newFont = $dom->createElement('span');
if(!empty($style)) {
$newFont->setAttribute('style', $style);
}
// Copy all children into a basic array to avoid an iterator
// on a changing tree
$children = iterator_to_array($font->childNodes);
foreach ($children as $child) {
// This has a side effect of removing the child from its old
// location, which changes the tree
$newFont->appendChild($child);
}
// Replace the parent's child, which changes the tree
$font->parentNode->replaceChild($newFont, $font);
// query again on the new tree
$fonts = $xPath->query('//font');
}
使用XSL可以将标记更改为跨度
<?php
$dom = new DOMDocument();
$dom->loadXML('<font color="#ff0000">Lorem <font size="4">ipsum dolor</font> sit amet</font>');
echo "Starting Point:" . $dom->saveXML() . PHP_EOL;
$xsl = new DOMDocument('1.0', 'UTF-8');
// Could be a seperate file
$xsl->loadXML(<<<XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<!-- Identity rule -->
<xsl:template match="@*|node()"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:template>
<xsl:template match="text()"><xsl:value-of disable-output-escaping="yes" select="."/></xsl:template>
<xsl:template match="font">
<xsl:element name="span">
<xsl:attribute name="style" xsl:space="default">
<xsl:if test="@size">font-size: <xsl:value-of select="round(@size * 10 div 2) div 10" /> em;</xsl:if>
<xsl:if test="@color">color: <xsl:value-of select="@color" />;</xsl:if>
</xsl:attribute>
<xsl:apply-templates select="node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
XSLT
);
$proc = new XSLTProcessor();
$proc->importStylesheet($xsl);
echo $proc->transformToXML($dom);
使用XSL可以将标记更改为span
<?php
$dom = new DOMDocument();
$dom->loadXML('<font color="#ff0000">Lorem <font size="4">ipsum dolor</font> sit amet</font>');
echo "Starting Point:" . $dom->saveXML() . PHP_EOL;
$xsl = new DOMDocument('1.0', 'UTF-8');
// Could be a seperate file
$xsl->loadXML(<<<XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<!-- Identity rule -->
<xsl:template match="@*|node()"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:template>
<xsl:template match="text()"><xsl:value-of disable-output-escaping="yes" select="."/></xsl:template>
<xsl:template match="font">
<xsl:element name="span">
<xsl:attribute name="style" xsl:space="default">
<xsl:if test="@size">font-size: <xsl:value-of select="round(@size * 10 div 2) div 10" /> em;</xsl:if>
<xsl:if test="@color">color: <xsl:value-of select="@color" />;</xsl:if>
</xsl:attribute>
<xsl:apply-templates select="node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
XSLT
);
$proc = new XSLTProcessor();
$proc->importStylesheet($xsl);
echo $proc->transformToXML($dom);
导言
从下面的对话中
雷基尔
为什么不直接使用正则表达式呢
乔纳夫
我已经做了很长一段时间了,但我正在尝试切换到DOMDocument/html5lib。。。codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html`
我完全同意这一点,这就是为什么我认为这不是DomDocument
和Regular expression
的工作,因为您正在处理HTML 5中不再支持的折旧HTML标记的问题
含意
这意味着font
不是您可能还需要更换的唯一问题
- 首字母缩略词
- 小程序
- 基本字体
- 大的
- 居中
- 迪尔
- 框架
- 框架集
- 无框
- 罢工
- tt
- xmp
使用整洁的
我会推荐一种设计,这样你就不必做你要做的事情
表单PHP文档
Tidy是Tidy HTMLclean和repair实用程序的绑定,它不仅允许您清理和以其他方式操作HTML文档,,还允许您遍历文档树
实例
$html='Lorem ipsum door sit amet';
$config=array(
“缩进”=>true,
“仅显示正文”=>false,
“干净”=>正确,
“输出xhtml”=>true,
“保留实体”=>true);
$tidy=新的tidy();
echo$tidy->repairString($html,$config,'UTF8');
输出
<!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>
/**/
Lorem ipsum dolor sit amet
有关示例,请参见
更好的窗台:HTMLPurifier
您可以使用,它也可以使用Tidy来清理HTML,您所需要的只是设置TidyLevel
HTML净化器是一个标准兼容的HTML过滤器库,用PHP编写。HTML净化器不仅将通过彻底审核、安全且允许的白名单删除所有恶意代码(更好地称为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);
require_once'htmlpurifier-4.4.0/library/htmlpurifier.auto.php';
$html='Lorem ipsum dolor sit amet';
$config=HTMLPurifier_config::createDefault();
$config->set('HTML.TidyLevel','heavy');
$punizer=新的HTMLPurifier($config);
$clean=$purizer->purify($html);
var_dump($清洁);
输出
string '<span style="color:#ff0000;">Lorem <span style="font-size:large;">ipsum dolor</span> sit amet</span>' (length=100)
字符串“Lorem ipsum dolor sit amet”(长度=100)
我要一份文件
如果你想要的只是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()));
$html='Lorem ipsum door sit amet';
$dom=新的DOMDocument();
$dom->loadHTML($html);
$nodes=iterator_to_数组($dom->getElementsByTagName('font'));
foreach($font形式的节点){
$css=array();
$font->hasAttribute('size')和$css[]='font size:'。舍入($font->getAttribute('size')/2,1)。'em;';
$font->hasAttribute('color')和$css[]='color:'。$font->getAttribute('color');';
$span=$dom->createElement('span');
$children=array();
foreach($font->childNodes作为$child)
$children[]=$child;
foreach($childrenas$child)
$span->appendChild($child);
$span->setAttribute('style',内爆(';',$css));
$font->parentNode->replaceChild($span,$font);
}
回声“;
$dom->formatOutput=true;
打印(htmlentities($dom->saveXML());
简介
从下面的对话中
雷基尔
为什么不直接使用正则表达式呢
乔纳夫
我已经做了很长一段时间了,但我正在尝试切换到DOMDocument/html5lib。。。codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html`
我完全同意这一点,这就是为什么我认为这不是DomDocument
和Regular expression
的工作,因为您正在处理HTML 5中不再支持的折旧HTML标记的问题
含意
这意味着font
不是您可能还需要更换的唯一问题
- 首字母缩略词
- 小程序
- 基本字体
- 大的
- 居中
- 迪尔
- 框架
- 框架集
- 无框
- 罢工
- tt
- xmp
使用整洁的
我会推荐一种设计,这样你就不必做你要做的事情
表单PHP文档
Tidy是Tidy HTMLclean和repair实用程序的绑定,该实用程序允许