Javascript DOMDocument-从正文中获取脚本文本
我试图做的是从body标签中获取脚本,但只获取具有文本而不是脚本链接的脚本 例如,Javascript DOMDocument-从正文中获取脚本文本,javascript,php,jquery,domdocument,Javascript,Php,Jquery,Domdocument,我试图做的是从body标签中获取脚本,但只获取具有文本而不是脚本链接的脚本 例如,console.log(“用于测试运行”) 不是包含文件src的脚本 我想把这些脚本放在之前的页面末尾 到目前为止我有 echo "<pre>"; echo "reaches 1 <br />"; //work for inpage scripts $mainBody = @$dom-&g
console.log(“用于测试运行”)代码>
不是包含文件src的脚本
我想把这些脚本放在
之前的页面末尾
到目前为止我有
echo "<pre>";
echo "reaches 1 <br />";
//work for inpage scripts
$mainBody = @$dom->getElementsByTagName('body')->item(0);
foreach (@$dom->getElementsByTagName('body') as $head) {
echo "reaches 2";
foreach (@$head->childNodes as $node) {
echo "reaches 3";
var_dump($node);
if ($node instanceof DOMComment) {
if (preg_match('/<script/i', $node->nodeValue)){
$src = $node->nodeValue;
echo "its a node";
var_dump($node);
}
}
if ($node->nodeName == 'script' && $node->attributes->getNamedItem('type')->nodeValue == 'text/javascript') {
if (@$src = $node->attributes->getNamedItem('src')->nodeValue) {
// yay - $src was true, so we don't do anything here
} else {
$src = $node->nodeValue;
}
echo "its a node2";
var_dump($node);
}
if (isset($src)) {
$move = ($this->params->get('exclude')) ? true : false;
foreach ($omit as $omitit) {
if (preg_match($omitit, $src) == 1) {
$move = ($this->params->get('exclude')) ? false : true;
break;
}
}
if ($move)
$moveme[] = $node;
unset($src);
}
}
}
foreach ($moveme as $moveit) {
echo "Moving";
print_r($moveit);
$mainBody->appendChild($moveit->cloneNode(true));
if ($pretty) {
$mainBody->appendChild($newline->cloneNode(false));
}
$moveit->parentNode->removeChild($moveit);
}
$mainBody = $xhtml ? $dom->saveXML() : $dom->saveHTML();
JResponse::setBody($sanitize?preg_replace($this->sanitizews['search'],$this->sanitizews['replace'],$mainBody):$mainBody);
function onAfterRender() {
$app = JFactory::getApplication();
$doc = JFactory::getDocument();
/* test that the page is not administrator && test that the document is HTML output */
if ($app->isAdmin() || $doc->getType() != 'html')
return;
$pretty = (int)$this->params->get('pretty', 0);
$stripcomments = (int)$this->params->get('stripcomments', 0);
$sanitize = (int)$this->params->get('sanitize',0);
$debug = (int)$app->getCfg('debug',0);
if($debug) $pretty = true;
$omit = array();
/* now we know this is a frontend page and it is html - begin processing */
/* first - prepare the omit array */
if (strlen(trim($this->params->get('omit'))) > 0) {
foreach (explode("\n", $this->params->get('omit')) as $omitme) {
$omit[] = '/' . str_replace(array('/', '\''), array('\/', '\\\''), trim($omitme)) . '/i';
}
unset($omitme);
}
$moveme = array();
$dom = new DOMDocument();
$dom->recover = true;
$dom->substituteEntities = true;
if ($pretty) {
$dom->formatOutput = true;
} else {
$dom->preserveWhiteSpace = false;
}
$source = JResponse::getBody();
/* DOMDocument can get quite vocal when malformed HTML/XHTML is loaded.
* First we grab the current level, and set the error reporting level
* to zero, afterwards, we return it to the original value. This trickery
* is used to keep the logs clear of DOMDocument protests while loading the source.
* I promise to set the level back as soon as I'm done loading source...
*/
if(!$debug) $erlevel = error_reporting(0);
$xhtml = (preg_match('/XHTML/', $source)) ? true : false;
switch ($xhtml) {
case true:
$dom->loadXML($source);
break;
case false:
$dom->loadHTML($source);
break;
}
if(!$debug) error_reporting($erlevel); /* You see, error_reporting is back to normal - just like I promised */
if ($pretty) {
$newline = $dom->createTextNode("\n");
}
if($sanitize && !$debug && !$pretty) {
$this->_sanitizeCSS($dom->getElementsByTagName('style'));
}
if ($stripcomments && !$debug) {
$comments = $this->_domComments($dom);
foreach ($comments as $node)
if (!preg_match('/\[endif]/i', $node->nodeValue)) // we don't remove IE conditionals
if ($node->parentNode->nodeName != 'script') // we also don't remove comments in javascript because some developers write JS inside of a comment
$node->parentNode->removeChild($node);
}
$body = @$dom->getElementsByTagName('footer')->item(0);
foreach (@$dom->getElementsByTagName('head') as $head) {
foreach (@$head->childNodes as $node) {
if ($node instanceof DOMComment) {
if (preg_match('/<script/i', $node->nodeValue))
$src = $node->nodeValue;
}
if ($node->nodeName == 'script' && $node->attributes->getNamedItem('type')->nodeValue == 'text/javascript') {
if (@$src = $node->attributes->getNamedItem('src')->nodeValue) {
// yay - $src was true, so we don't do anything here
} else {
$src = $node->nodeValue;
}
}
if (isset($src)) {
$move = ($this->params->get('exclude')) ? true : false;
foreach ($omit as $omitit) {
if (preg_match($omitit, $src) == 1) {
$move = ($this->params->get('exclude')) ? false : true;
break;
}
}
if ($move)
$moveme[] = $node;
unset($src);
}
}
}
foreach ($moveme as $moveit) {
$body->appendChild($moveit->cloneNode(true));
if ($pretty) {
$body->appendChild($newline->cloneNode(false));
}
$moveit->parentNode->removeChild($moveit);
}
//work for inpage scripts
$xpath = new DOMXPath($dom);
$script_tags = $xpath->query('//body//script[not(@src)]');
$mainBody = @$dom->getElementsByTagName('body')->item(0);
foreach ($script_tags as $tag) {
$mainBody->appendChild($tag->cloneNode(true));
$tag->parentNode->removeChild($tag);
}
$body = $xhtml ? $dom->saveXML() : $dom->saveHTML();
JResponse::setBody($sanitize?preg_replace($this->sanitizews['search'],$this->sanitizews['replace'],$body):$body);
}
";
更新3
我为Joomla工作,试图将脚本移动到页面的页脚。我使用了scriptsdown插件,该插件将脚本从head标记移动到底部。但是页面中间带有的脚本没有移动到底部,因此导致inpage脚本无法正确响应
我的问题现在解决了。发布我的解决方案代码,以便将来它是否可以帮助其他人
foreach ($script_tags as $tag) {
var_dump($tag->nodeValue);
$moveme[] = $tag;
}
函数onAfterRender(){
$app=JFactory::getApplication();
$doc=JFactory::getDocument();
/*测试页面是否不是管理员&测试文档是否为HTML输出(&T)*/
如果($app->isAdmin()| |$doc->getType()!='html')
返回;
$pretty=(int)$this->params->get('pretty',0);
$stripcomments=(int)$this->params->get('stripcomments',0);
$sanitize=(int)$this->params->get('sanitize',0);
$debug=(int)$app->getCfg('debug',0);
如果($debug)$pretty=true;
$omit=array();
/*现在我们知道这是一个前端页面,它是html-开始处理*/
/*首先-准备省略数组*/
if(strlen(trim($this->params->get('omit'))>0){
foreach(分解(“\n”,$this->params->get('omit'))为$ommitme){
$omit[]='/'.str_替换(数组('/','\'')、数组('\/','\\'')、修剪($omitme))。/i';
}
未设置($忽略我);
}
$moveme=array();
$dom=新的DOMDocument();
$dom->recover=true;
$dom->substituteEntities=true;
如果($pretty){
$dom->formatOutput=true;
}否则{
$dom->preserveWhiteSpace=false;
}
$source=JResponse::getBody();
/*当加载格式不正确的HTML/XHTML时,DOMDocument可能会非常响亮。
*首先,我们获取当前级别,并设置错误报告级别
*然后,我们将其返回到原始值。这是一个骗局
*用于在加载源时清除日志中的文档。
*我保证在加载完源代码后立即将级别设置回原来的水平。。。
*/
如果(!$debug)$erlevel=错误报告(0);
$xhtml=(preg_match('/xhtml/',$source))?true:false;
交换机($xhtml){
大小写正确:
$dom->loadXML($source);
打破
案例错误:
$dom->loadHTML($source);
打破
}
如果(!$debug)错误报告($erlevel);/*你看,错误报告会恢复正常-就像我承诺的那样*/
如果($pretty){
$newline=$dom->createTextNode(“\n”);
}
如果($sanitize&&!$debug&&!$pretty){
$this->_sanitizeCSS($dom->getElementsByTagName('style');
}
如果($stripcomments&&!$debug){
$comments=$this->\u domComments($dom);
foreach($node作为$comments)
如果(!preg_match('/\[endif]/i',$node->nodeValue))//我们不删除IE条件
如果($node->parentNode->nodeName!=“script”)//我们也不会删除javascript中的注释,因为有些开发人员在注释中编写JS
$node->parentNode->removeChild($node);
}
$body=@$dom->getElementsByTagName('footer')->项(0);
foreach(@$dom->getElementsByTagName('head')作为$head){
foreach(@$head->childNodes作为$node){
if($node instanceof domcoment){
if(preg_match('/nodeValue;
}
}
如果(isset($src)){
$move=($this->params->get('exclude'))?true:false;
foreach($ommit作为$ommitit省略){
if(preg_match($ommitit,$src)==1){
$move=($this->params->get('exclude'))?false:true;
打破
}
}
如果($move)
$moveme[]=$node;
未结算($src);
}
}
}
foreach($moveme作为$moveit){
$body->appendChild($moveit->cloneNode(true));
如果($pretty){
$body->appendChild($newline->cloneNode(false));
}
$moveit->parentNode->removeChild($moveit);
}
//为inpage脚本工作
$xpath=newdomxpath($dom);
$script_tags=$xpath->query('//body//script[not(@src)]);
$mainBody=@$dom->getElementsByTagName('body')->项(0);
foreach($script_标记为$tag){
$mainBody->appendChild($tag->cloneNode(true));
$tag->parentNode->removeChild($tag);
}
$body=$xhtml?$dom->saveXML():$dom->saveHTML();
JResponse::setBody($sanitize?preg_replace($this->sanitizews['search'],$this->sanitizews['replace'],$body):$body);
}
为了只获取不具有
src
属性的节点,最好使用DOMXPath
:
变量$script\u tags
现在是一个DOMNodeList
对象,它包含所有脚本标记。
现在,您可以在DOMNodeList
上循环以获取所有节点,并对它们执行任何操作:
那么这里发生了什么?错误在哪里?只是一大块code@RodrigoDuterte我更新了我的问题。事实上,我的代码在页面的body标记下找不到脚本标记。或者像下面一样使用xpath,或者只是$mainBody->getElementsByTagName('*')
,我更喜欢
$xpath = new DOMXPath($dom);
$script_tags = $xpath->query('//body//script[not(@src)]');
foreach ($script_tags as $tag) {
var_dump($tag->nodeValue);
$moveme[] = $tag;
}