Javascript DOMDocument-从正文中获取脚本文本

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

我试图做的是从body标签中获取脚本,但只获取具有文本而不是脚本链接的脚本

例如,
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;
}