最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - Replace all the ocurrance of a string in an element - Stack Overflow

matteradmin6PV0评论

I want to replace a particular string in (the text of) all the descendant elements of a given element.

innerHTML cannot be used as this sequence can appear in attributes. I have tried using XPath, but it seems the interface is essentially read-only. Because this is limited to one element, functions like document.getElementsByTagName cannot be used either.

Could any suggest any way to do this? Any jQuery or pure DOM method is acceptable.

Edit:

Some of the answers are suggesting the problem I was trying to work around: modifying the text directly on an Element will cause all non-Text child nodes to be removed.

So the problem essentially es down to how to efficiently select all the Text nodes in a tree. In XPath, you can easily do it as //text(), but the current XPath interface does not allow you to change these Text nodes it seems.

One way to do this is by recursion as shown in the answer by Bergi. Another way is to use the find('*') selector of jQuery, but this is a bit more expensive. Still waiting to see if there' are better solutions.

I want to replace a particular string in (the text of) all the descendant elements of a given element.

innerHTML cannot be used as this sequence can appear in attributes. I have tried using XPath, but it seems the interface is essentially read-only. Because this is limited to one element, functions like document.getElementsByTagName cannot be used either.

Could any suggest any way to do this? Any jQuery or pure DOM method is acceptable.

Edit:

Some of the answers are suggesting the problem I was trying to work around: modifying the text directly on an Element will cause all non-Text child nodes to be removed.

So the problem essentially es down to how to efficiently select all the Text nodes in a tree. In XPath, you can easily do it as //text(), but the current XPath interface does not allow you to change these Text nodes it seems.

One way to do this is by recursion as shown in the answer by Bergi. Another way is to use the find('*') selector of jQuery, but this is a bit more expensive. Still waiting to see if there' are better solutions.

Share Improve this question edited May 23, 2017 at 12:17 CommunityBot 11 silver badge asked Jul 17, 2012 at 15:33 billc.cnbillc.cn 7,3363 gold badges42 silver badges82 bronze badges 2
  • jQuery selectors let you traverse and modify the dom, access the descendants and the siblings of an element. And much more. – Alberto De Caro Commented Jul 17, 2012 at 15:44
  • @ADC, unfortunately there's nothing like XPath's text() selector.... – billc.cn Commented Jul 17, 2012 at 16:03
Add a ment  | 

4 Answers 4

Reset to default 4

Just use a simple selfmade DOM-iterator, which walks recursively over all nodes:

(function iterate_node(node) {
    if (node.nodeType === 3) { // Node.TEXT_NODE
        var text = node.data.replace(/any regular expression/g, "any replacement");
        if (text != node.data) // there's a Safari bug
            node.data = text;
    } else if (node.nodeType === 1) { // Node.ELEMENT_NODE
        for (var i = 0; i < node.childNodes.length; i++) {
            iterate_node(node.childNodes[i]); // run recursive on DOM
        }
    }
})(content); // any dom node

A solution might be to surf through all available nodes (TextNodes included) and apply a regexp pattern on the results. To grab TextNodes as well, you need to invoke jQuerys .contents(). For instance:

var search = "foo",
    replaceWith = 'bar',
    pattern = new RegExp( search, 'g' );


function searchReplace( root ) {
    $( root ).contents().each(function _repl( _, node ) {
        if( node.nodeType === 3 )
            node.nodeValue = node.nodeValue.replace( pattern, replaceWith );
        else searchReplace( node );
    });
}

$('#apply').on('click', function() {
    searchReplace( document.getElementById('rootNode') );
});

Example: http://jsfiddle/h8Rxu/3/

Reference: .contents()

Using jQuery:

$('#parent').children().each(function () {
    var that = $(this);

    that.text(that.text().replace('test', 'foo'));
});

If you prefer to search through all children instead of just immediate children, use .find() instead.

http://jsfiddle/ExwDx/

Edit: Documentation for children, each, text, and find.

Sorry, just got it myself:

$('#id').find('*').each(function(){
    $.each(this.childNodes, function() {
        if (this.nodeType === 3) {
            this.data = this.data.toUpperCase();
        }
    })
})

I used toUpperCase() here to make the result more obvious, but any String operation would be valid there.

Post a comment

comment list (0)

  1. No comments so far