问题描述
我正在用 PHP 加载远程文件,然后尝试用 DomDocument
解析它。该文件包含 HTML、CSS(在 style
标签内)和 JavaScript(在 script
标签内)。然后我通过将 html
或 css
或 js
传递给解析它的函数来单独加载它。这个想法是我可以使用核心 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();
这会导致一些问题:
- 在 CSS 和 JavaScript 输出中,它保留了
style
或script
标记,我正在尝试找出如何将其删除。 - 在 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,它应该能让您了解如何修改您的代码。