删除脚本和样式标记中的所有内容
Remove everything within script and style tags
我有一个名为$articleText
的变量,它包含html代码。在<script>
和<style>
html元素中存在script
和style
代码。我想扫描$articleText
并删除这些代码。如果我也可以删除实际的html元素<script>
、</script>
、<style>
和</style>
,我也会这样做。
我想我需要使用正则表达式,但我不熟练。
有人能帮忙吗?
我希望我能提供一些代码,但正如我所说,我不擅长正则表达式,所以我没有任何东西可以展示。
我不能使用DOM。我需要特别针对这些特定的标签使用regex
不要在HTML上使用RegEx。PHP提供了一种用于解析DOM结构的工具,称为DomDocument。
<?php
// some HTML for example
$myHtml = '<html><head><script>alert("hi mom!");</script></head><body><style>body { color: red;} </style><h1>This is some content</h1><p>content is awesome</p></body><script src="someFile.js"></script></html>';
// create a new DomDocument object
$doc = new DOMDocument();
// load the HTML into the DomDocument object (this would be your source HTML)
$doc->loadHTML($myHtml);
removeElementsByTagName('script', $doc);
removeElementsByTagName('style', $doc);
removeElementsByTagName('link', $doc);
// output cleaned html
echo $doc->saveHtml();
function removeElementsByTagName($tagName, $document) {
$nodeList = $document->getElementsByTagName($tagName);
for ($nodeIdx = $nodeList->length; --$nodeIdx >= 0; ) {
$node = $nodeList->item($nodeIdx);
$node->parentNode->removeChild($node);
}
}
你可以在这里试试:https://eval.in/private/4f225fa0dcb4eb
文档
DomDocument
-http://php.net/manual/en/class.domdocument.phpDomNodeList
-http://php.net/manual/en/class.domnodelist.phpDomDocument::getElementsByTagName
-http://us3.php.net/manual/en/domdocument.getelementsbytagname.php
即使regex对于这类任务也不是一个好工具,对于简单的小任务来说,它也可以工作。
如果您只想删除标签的内部文本,请使用:
preg_replace('/(<(script|style)'b[^>]*>).*?(<'/'2>)/is', "$1$3", $txt);
请参阅此处的演示。
如果您还想删除标记,那么上面代码中的替换字符串将为空,所以只有""
。
我认为这应该满足您的需要(假设没有嵌套的脚本和样式标记):
preg_replace('/(<script[^>]*>.+?<'/script>|<style[^>]*>.+?<'/style>)/is', '', $articleText);
以下是示例数据:
$in = '
<html>
<head>
<script type="text/javascript">window.location="somehwere";</script>
<style>
.someCSS {border:1px solid black;}
</style>
</head>
<body>
<p>....</p>
<div>
<script type="text/javascript">document.write("bad stuff");</script>
</div>
<ul>
<li><style type="text/css">#moreCSS {font-weight:900;}</style></li>
</ul>
</body>
</html>';
现在是拼写出来的版本:
$dom = new DOMDocument('1.0','UTF-8');
$dom->loadHTML($in);
removeByTag($dom,'style');
removeByTag($dom,'script');
var_dump($dom->saveHTML());
function removeByTag($dom,$tag) {
$nodeList = $dom->getElementsByTagName($tag);
removeAll($nodeList);
}
function removeAll($nodeList) {
for ( $i = $nodeList->length; --$i >=0; ) {
removeSelf($nodeList->item($i));
}
}
function removeSelf($node) {
$node->parentNode->removeChild($node);
}
还有一个替代方案(做同样的事情,只是没有函数声明):
$dom = new DOMDocument('1.0','UTF-8');
$dom->loadHTML($in);
for ( $list = $dom->getElementsByTagName('script'), $i = $list->length; --$i >=0; ) {
$node = $list->item($i);
$node->parentNode->removeChild($node);
}
for ( $list = $dom->getElementsByTagName('style'), $i = $list->length; --$i >=0; ) {
$node = $list->item($i);
$node->parentNode->removeChild($node);
}
var_dump($dom->saveHTML());
诀窍是在删除节点时向后迭代。getElementsByTagName将为您遍历整个DOM,因此您不必(这些都没有ChildNodes、nextSibling、nextChildd之类的东西)。
也许最好的解决方案是介于这两个极端例子之间。
我忍不住了,这可能是我建议的最好版本。它不包括一个增量器($i
)来把事情搞砸,并从自下而上删除:
$dom = new DOMDocument('1.0','UTF-8');
$dom->loadHTML($in);
removeElementsByTagName($dom,'script');
removeElementsByTagName($dom,'style');
function removeElementsByTagName($dom,$tagName) {
$list = $dom->getElementsByTagName($tagName);
while ( $node = $list->item(0) ) {
$node->parentNode->removeChild($node);
}
}
var_dump($dom->saveHTML());
删除节点时,它们会在父节点的子列表中向上移动,因此1变为0,2变为1,依此类推。继续执行此操作(while
),直到不再存在为止(->item
返回null)。还将其封装在一个可重用函数中。
假设这既是为了不让你的设计被随机风格搞砸,也是为了保护你的网站不受用户脚本的影响,删除这些标签并不能单独保证你的安全。
考虑事件属性(例如:onmouseover,onclick)的情况:
<h1 onclick="console.log('user made this happen');">User Scripting Test</h1>
甚至更糟的
<h1 onclick='function addCSSRule(a,b,c,d){"insertRule"in a?a.insertRule(b+"{"+c+"}",d):"addRule"in a&&a.addRule(b,c,d)}var style=document.createElement("style");style.appendChild(document.createTextNode("")),document.head.appendChild(style),sheet=style.sheet,addCSSRule(sheet,"*","color: #ff0!important");'>Messing with your styles!</h1>
这样一来,开始在文档中插入各种各样的东西就相当简单了。
样式表mods的最后一个例子取自David Walsh-https://davidwalsh.name/add-rules-stylesheets
唯一的解决方案
是使用一个经过验证的专门从事这方面的第三方库。我建议使用HTML净化器。它将消除用户输入中的样式、脚本和讨厌的事件属性。
要做到这一点,正则表达式将非常迟钝,因为标签中可能存在标签,以及标签属性等混淆结构。
我建议在DOM(PHP或JavaScript)中这样做,它可以通过实际解析来识别和删除不需要的标签。
- 当包含另一个asp文件时,是否也包含所有引用的样式和脚本页面
- 无法通过内容脚本使用jQuery更改HTML元素的样式
- 尝试在随机文本和图像脚本中添加样式/更改字体
- 在呈现HTML样式和脚本时加载启动页
- 正文中的 CSS 样式表和脚本.可能
- 如何防止 TinyMCE 将 CDATA 添加到<脚本>标签中,并注释掉<样式>标签
- 用于丢失文本样式的脚注的Indesign脚本
- 保留,但停用样式表&脚本
- dist中的GruntJS配置样式和脚本路径
- 删除脚本和样式标记中的所有内容
- 压缩脚本和样式,并将所有js和样式引用合并为单个引用,以优化网站性能
- 有没有办法从 Javascript 中的函数中调用脚本标签和样式标签
- 外部样式表或脚本文件前面的“$”
- 正文 HTML 中的样式和脚本
- 使用 Javascript 分配样式与在服务器端脚本中分配样式
- 包含块的样式/脚本
- 如何将CSS样式应用于由Javascript脚本注入和样式化的HTML,这是我无法控制的
- TinyMCE 中没有<样式>标签的脚本脚本
- SugarCRM新鲜库存安装样式和脚本未正确链接
- 没有MVC或类似功能的ASP.NET的任何脚本/样式表压缩器