【问题标题】:Edit elements in the jsdom window and save the window as a new HTML file?在 jsdom 窗口中编辑元素并将窗口另存为新的 HTML 文件?
【发布时间】:2015-07-19 03:56:38
【问题描述】:

我想加载一个 HTML 文件(使用 fs.read),使用 jsdom 加载 DOM,然后更改正文节点的文本(通过 jquery)。然后我想将编辑后的 ​​DOM 窗口保存为 HTML 文件。有没有办法做到这一点?我使用的代码如下:

fs.readFile(file, 'utf8', function(error, data) {
    jsdom.env(data, [], function (errors, window) {
        var $ = require('jquery')(window);
        $(document.body.getElementsByTagName("*")).each(function () {
            var content = $(this).text();
            var word = "\\b"+wordSuggestions.word+"\\b";
            var re = new RegExp(word, "g");
            content = content.replace(re, wordSuggestions.suggestion);
            $(this).text(content);
        });

        fs.writeFile(file, data, function (error){ // saving the new HTML file? What should I put instead of data? Window?
        });
    });
});

【问题讨论】:

  • 我认为$(document.body.getElementsByTagName("*")) 有两点错误。首先,它是 jQuery 和 javascript 选择器的组合。在 jQuery 中应该是 $("*"),在 javascript 中应该是 document.body.getElementsByTagName("*")。其次,是服务端代码,所以这里没有jQuery,除非我不了解jQuery的服务端实现。
  • 我忘记在这篇文章中包含 var $ = require('jquery')(window),所以我对其进行了编辑以包含它。使用 document.body.getElementsByTagName("*") (不带 jquery)时,我可以只编辑每个节点的文本吗?然后保存编辑好的html?
  • 不过,$(document.body.getElementsByTagName("*")) 没有意义,并且可能无效,即使加载了 jQuery。所以你告诉我你正在运行 jQuery server 端?我四处搜寻,我看不到使用它的地方,甚至说根本不可能。 jQuery 是为 DOM 操作而设计的,服务器上没有 DOM。这里有一些我不明白的地方。 fs 是一个 SERVER 模块,readwrite 只能从服务器实现,不能从浏览器实现。请确认这是一个 server 端脚本(= 不在浏览器中运行)并且您正在尝试在其中使用 jQuery。
  • 我是从另一个 stackoverflow 问题中得到的。这确实是一个服务器端脚本。我为此使用 jquery 的 npm 模块 (npmjs.com/package/jquery)。
  • 这是一个构建您自己版本的 jQuery 的模块,而不是在服务器端使用它。不过,jQuery 是 client 端的,它不在服务器上运行。您的服务器脚本必须使用纯 JavaScript。 document.body.getElementsByTagName 确实毫无意义,因为在服务器上,没有 DOM,没有元素,也没有标签(没有名称)。这是行不通的,您正在混合前端和后端代码。这就像将javascript和PHP混合在一起,希望它能起作用,这是不可能的。

标签: javascript jquery html node.js jsdom


【解决方案1】:

没有jsdom.env()了,我觉得这个例子更容易理解:

const fs = require('fs');
const jsdom = require('jsdom');
const jquery = require('jquery');

fs.readFile('1.html', 'utf8', (err, data) => {
    const dom = new jsdom.JSDOM(data);
    const $ = jquery(dom.window);
    $('body').html('');
    fs.writeFile('2.html', dom.serialize(), err => {
        console.log('done');
    });
});

【讨论】:

    【解决方案2】:

    这是一个如何做的例子。我以您的代码为基础,但对其进行了一些简化,以便我可以执行代码并说明如何执行此操作。以下代码读取foo.html 并将文本modified! 添加到所有p 元素,然后将其写入out.html。您缺少的主要内容是window.document.documentElement.outerHTML

    var jsdom = require("jsdom");
    var fs = require("fs");
    
    fs.readFile('foo.html', 'utf8', function(error, data) {
        jsdom.env(data, [], function (errors, window) {
            var $ = require('jquery')(window);
            $("p").each(function () {
                var content = $(this).text();
                $(this).text(content + " modified!");
            });
    
            fs.writeFile('out.html', window.document.documentElement.outerHTML,
                         function (error){
                if (error) throw error;
            });
        });
    });
    

    【讨论】:

    • 还有没有办法选择所有文本节点而不是所有p元素?
    • 没有返回所有文本节点的 jQuery 函数(在术语“文本节点”的 DOM 意义上)。可以遍历 DOM 树并一一处理所有文本节点,但这不涉及 jQuery。如果您想在此处编辑您的问题以提示读者解决“选择所有文本节点”问题,我强烈建议不要这样做。您已经提出了一个问题,该问题被认为是关于从 jsdom 保存修改后的数据,我已经回答了。在获得解决原始问题的答案后向问题添加新问题,社区并不认可。
    • 另一件事是,如果你将 jsdom 问题与你应该如何处理文本节点的问题结合起来,你实际上是在结合实际上可以独立解决的问题。因此,与其受益于每个知道 jsdom 的人的输入来解决 jsdom 问题,以及每个知道 DOM(也许还有 jQuery)的人的输入来解决文本节点问题,你必须依靠 intersection i> 知道 jsdom jQuery 的人,这是一个较小的集合。您还可以降低问题对其他人有用的可能性并获得支持。
    • 感谢您的建议。我暂时不会编辑问题并使用所有 p 节点。
    • 这将剥离文档类型。试试await promisify(fs.writeFile)('out.html, ${dom.window.document.documentElement.outerHTML}, 'utf-8')
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 2014-12-18
    相关资源
    最近更新 更多