JavaScript:删除 HTML 标签、修改标签/文本以及将标签重新插入

标签 javascript html parsing

我正在尝试找到一种方法来删除 HTML 文档中的所有标签,存储它们的位置,修改剩余的文本,然后将标签重新插入它们所属的位置。

要点

  • 稍后我需要重新插入标签,因此我需要存储每个标签的位置
    • 因此,建议使用 DOMParser here不会工作
  • 这将在外部网站上完成,而不是我自己的
  • 正则表达式建议here ( /<(?:.|\n)*?>/gm ) 会起作用,但它也会错误地捕获 <>包含 html
  • 这似乎有效:https://regexr.com/3npgn ( /<[^<|>]*>/g ),但我读到使用正则表达式并不是解析 html 的好方法。是否存在这会失败的情况?

完整代码:

function foo() {
    var elementHtml = document.body.innerHTML;
    var tags = [];
    var tagLocations = [];
    //var htmlTagRegEx =/<{1}\/{0,1}\w+>{1}/;
    var htmlTagRegEx =/<[^<]*>/;

    //Strip the tags from the elementHtml and keep track of them
    var htmlTag;
    while (htmlTag = elementHtml.match(htmlTagRegEx)) {
        console.log('htmlTag: ', htmlTag);
        tagLocations[tagLocations.length] = elementHtml.search(htmlTagRegEx);
        tags[tags.length] = htmlTag;
        elementHtml = elementHtml.replace(htmlTag, '');
    }
}

编辑

为了避免混淆,下面是对我想要完成的事情的详细解释:

在整个(外部)网站(不包括标签)的文本中搜索字符串,如果找到则更改这些实例的样式(例如颜色)。

这是我的尝试:

    function highlightInElement(elementId, text) {
        var elementHtml = document.body.innerHTML;
        var tags = [];
        var tagLocations = [];
        //var htmlTagRegEx =/<{1}\/{0,1}\w+>{1}/;
        var htmlTagRegEx =/<[^<]*>/;
        //Strip the tags from the elementHtml and keep track of them
        var htmlTag;
        while (htmlTag = elementHtml.match(htmlTagRegEx)) {
            //console.log('htmlTag: ', htmlTag);
            tagLocations[tagLocations.length] = elementHtml.search(htmlTagRegEx);
            tags[tags.length] = htmlTag;
            elementHtml = elementHtml.replace(htmlTag, '');
        }
        console.log('elementHtml: ', elementHtml);

        //Search for the text in the stripped html
        var textLocation = elementHtml.search(text);
        if (textLocation) {
            //Add the highlight
            var highlightHTMLStart = '<span class="highlight">';
            var highlightHTMLEnd = '</span>';
            elementHtml = elementHtml.replace(text, highlightHTMLStart + text + highlightHTMLEnd);

            //plug back in the HTML tags
            var textEndLocation = textLocation + text.length;
            for (let i = tagLocations.length - 1; i >= 0; i--) {
                var location = tagLocations[i];
                if (location > textEndLocation) {
                    location += highlightHTMLStart.length + highlightHTMLEnd.length;
                } else if (location > textLocation) {
                    location += highlightHTMLStart.length;
                }
                elementHtml = elementHtml.substring(0, location) + tags[i] + elementHtml.substring(location);
            }
        }

        //Update the html of the element
        document.body.innerHTML = elementHtml;
    }

    highlightInElement(document.documentElement, fooInputTxt.value);

最佳答案

To avoid confusion, here follows a detailed explanation of what I want to accomplish: Search for a string in the text of a whole (external) website (not including the tags), then change the styling (e.g. color) of those instances if found.

那么这正是你应该做的:)

首先,构建一个递归函数来遍历DOM并获取所有的文本节点:

function findTextNodes(node, ret) {
    var c = node.childNodes, i, l = c.length;
    for( i=0; i<l; i++) {
        switch(c[i].nodeType) {
            case 1: // element node
                findTextNodes(c[i], ret);
                break;
            case 3: // text node
                ret.push(c[i]);
                break;
        }
    }
}
var textNodes = [];
findTextNodes(document.body, textNodes);

现在您已经有了文档中所有文本节点的数组,您可以开始在它们中搜索您的目标。

function searchTextNodes(nodes, search) {
    var results = [], l = nodes.length, i,
        regex = new RegExp(search,'i'), match,
        span;
    for( i=0; i<l; i++) {
        while( (match = nodes[i].nodeValue.search(regex)) > -1) {
            nodes[i] = nodes[i].splitText(match);
            span = document.createElement('span');
            span.classList.add('highlight');
            nodes[i].parentNode.insertBefore(span, nodes[i]);
            nodes[i].splitText(search.length);
            span.appendChild(nodes[i]);
            nodes[i] = span.nextSibling;
        }
    }
}
searchTextNodes(textNodes, fooInputTxt.value);

然后...就是这样!对于额外的信用,这里是如何“撤消”搜索:

function undoSearch(root) {
    var nodes = root.querySelectorAll("span.highlight"),
        l = nodes.length, i;
    for( i=0; i<l; i++) {
        nodes[i].parentNode.replaceChild(nodes[i].firstChild, nodes[i]);
    }
    root.normalize();
}
undoSearch(document.body);

Demo on JSFiddle

关于JavaScript:删除 HTML 标签、修改标签/文本以及将标签重新插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49794417/

相关文章:

javascript - 如何以正确的方式捕获异常? [初学者]

html - 无法让 emacs 组织模式使用我的 CSS 文件

c - 将.csv文件解析为C中的二维数组

javascript - 可以在新创建的窗口上设置 onload() 吗?

javascript - 有没有一种好的方法可以使用 EJS 模板进行路由,避免与 Express 服务器重复?

javascript - AngularJS + CSS : best practice for a live preview?

html - 将表格与 div 并排放置

java - 解析包含右侧带有减号的数字的字符串

JavaScript、URL 解析、字符串操作、导航

javascript - 在加载新图表之前清除单个 svg