使用 DomDocument 从文件中分离 HTML、CSS 和 JavaScript

问题描述

我正在用 PHP 加载远程文件,然后尝试用 DomDocument 解析它。该文件包含 HTML、CSS(在 style 标签内)和 JavaScript(在 script 标签内)。然后我通过将 htmlcssjs 传递给解析它的函数来单独加载它。这个想法是我可以使用核心 wordpress 方法在适当的位置显示这些。

这是我设法得到的最接近的:

libxml_use_internal_errors( true );
$document = wp_remote_retrieve_body( $response ); // this is the remote HTML file
// create a new DomDocument object
$html = new DOMDocument( '1.0','UTF-8' );
// load the HTML into the DomDocument object (this would be your source HTML)
$html->loadHTML( $document,LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
if ( 'html' === $part ) {
    $xpath  = new DOMXPath( $html );
    $remove = $xpath->query( "//*[style or script]" );
    foreach ( $remove as $node ) {
        $node->parentNode->removeChild($node);
    }
} elseif ( 'css' === $part ) {
    $xpath  = new DOMXPath( $html );
    $remove = $xpath->query( "//*[not(self::style)]" );
    foreach ( $remove as $node ) {
        $node->parentNode->removeChild($node);
    }
} elseif ( 'js' === $part ) {
    $xpath  = new DOMXPath( $html );
    $remove = $xpath->query( "//*[not(self::script)]" );
    foreach ( $remove as $node ) {
        $node->parentNode->removeChild($node);
    }
}

ob_start();
echo $html->saveHTML();
$output = ob_get_contents();
ob_end_clean();

这会导致一些问题:

  1. 在 CSS 和 JavaScript 输出中,它保留了 stylescript 标记,我正在尝试找出如何将其删除
  2. 在 HTML 输出中,它保留了 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"><html><head></head><body>,我也想将其删除

我不确定我是否需要将其带往另一个方向,或者我是否只需要一个小东西来移除这些包装元素。但是我很难让 xpath 与我想要保留的元素相关联,而不是我想要删除的元素,这就是我最终的位置。

解决方法

对于您的 html 情况,您可以只保存 <body> 元素,而不是保存整个 DOMDocument。

libxml_use_internal_errors( true );
$document = wp_remote_retrieve_body( $response ); // this is the remote HTML file
// create a new DomDocument object
$html = new DOMDocument( '1.0','UTF-8' );
// load the HTML into the DomDocument object (this would be your source HTML)
$html->loadHTML( $document,LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
if ( 'html' === $part ) {
    // get all <body> elements
    $body_elements = $html->getElementsByTagName( 'body' );
    // it is to be assumed that there is only one <body> element.
    $body = $body_elements->item( 0 );
    // get the HTML contained within that body element
    $output = $body->ownerDocument->saveHTML( $body );
} else {
    // ...
}

对于 CSS 和 JS 元素,我不知道为什么你只需要获取它们的内部内容而不需要包含标签,但是与我们刚刚使用 $body 所做的类似的方法是可行的:1 . 选择元素, 2. foreach 循环遍历元素数组, 3. 获取每个元素的内部保存(我相信,但不确定这将是一个 DOMText 对象) 并连接这些字符串以创建最终的 $output 变量。

CSS 和 JS 的另一种方法:采用现有方法的 <script><tag> 元素簇,将它们插入到空白的 DOMDocument<head> 中以保存它们包含 <head> 作为 HTML 字符串,然后通过 WordPress 的 wp_enqueue_scripts 钩子上的匿名函数将该字符串加入队列:

/**
 * https://stackoverflow.com/questions/66361476/separate-html-css-and-javascript-from-file-with-domdocument?newreg=231eb52469c14d8c9c45ee9969df031a
 */
function wpse_66361476_alert() {
    $output = "<script>alert('hello');</script>"; // demonstration content
    add_action(
        'wp_enqueue_scripts',function() use ($output) {
            echo $output;
        }
    );
}
add_action('init','wpse_66361476_alert');

如果您不控制输出的 CSS 和 JS(和 HTML),这种方法很危险。在这里加载的任何内容都使用 iframe 可能会更好。

如果您的主机尚未使用前端缓存,要提高页面加载速度,您可能需要考虑使用 WordPress 的缓存功能缓存解析的元素。 Here's a short overview;与您的托管服务提供商联系,看看他们是否有具体的建议。

,

问题在于 DomNode(s)。查看 DOMDocument remove script tags from HTML source,它应该能让您了解如何修改您的代码。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...