Tách HTML khỏi JavaScript văn bản


655

Có cách nào dễ dàng để lấy một chuỗi html trong JavaScript và loại bỏ html không?

Câu trả lời:


760

Nếu bạn đang chạy trên một trình duyệt, thì cách dễ nhất là để trình duyệt làm điều đó cho bạn ...

function stripHtml(html)
{
   var tmp = document.createElement("DIV");
   tmp.innerHTML = html;
   return tmp.textContent || tmp.innerText || "";
}

Lưu ý: như mọi người đã lưu ý trong các nhận xét, điều này tốt nhất nên tránh nếu bạn không kiểm soát nguồn HTML (ví dụ: không chạy cái này trên bất cứ thứ gì có thể đến từ đầu vào của người dùng). Đối với những tình huống đó, bạn vẫn có thể để trình duyệt thực hiện công việc cho mình - xem câu trả lời của Saba về việc sử dụng DOMParser hiện có sẵn rộng rãi .


40
Chỉ cần nhớ rằng cách tiếp cận này khá không nhất quán và sẽ thất bại trong việc loại bỏ một số ký tự trong một số trình duyệt nhất định. Ví dụ: trong Prototype.js, chúng tôi sử dụng phương pháp này để thực hiện, nhưng khắc phục một số thiếu sót - github.com/
Khangax / prototype / blog / trên

11
Hãy nhớ khoảng trắng của bạn sẽ bị rối tung. Tôi đã từng sử dụng phương pháp này và sau đó gặp vấn đề vì một số mã sản phẩm nhất định chứa không gian kép, kết thúc là không gian đơn sau khi tôi lấy lại nội bộ từ DIV. Sau đó, mã sản phẩm không khớp với sau này trong ứng dụng.
Magnus Smith

11
@Magnus Smith: Có, nếu khoảng trắng là một mối quan tâm - hoặc thực sự, nếu bạn có nhu cầu về văn bản này không liên quan trực tiếp đến DOM DOM cụ thể mà bạn đang làm việc - thì tốt hơn hết bạn nên sử dụng một trong những thứ khác giải pháp được đưa ra ở đây. Ưu điểm chính của phương pháp này là 1) tầm thường và 2) sẽ xử lý đáng tin cậy các thẻ, khoảng trắng, thực thể, nhận xét, v.v ... giống như trình duyệt bạn đang chạy . Điều đó thường hữu ích cho mã máy khách web, nhưng không nhất thiết thích hợp để tương tác với các hệ thống khác có quy tắc khác nhau.
Shog9

220
Đừng sử dụng điều này với HTML từ một nguồn không đáng tin cậy. Để xem tại sao, hãy thử chạystrip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")
Mike Samuel

24
Nếu html chứa hình ảnh (thẻ img), hình ảnh sẽ được trình duyệt yêu cầu. Điều đó không tốt.
douyw

589
myString.replace(/<[^>]*>?/gm, '');

4
Không hoạt động <img src=http://www.google.com.kh/images/srpr/nav_logo27.png onload="alert(42)" nếu bạn tiêm qua document.writehoặc nối với một chuỗi có chứa >trước khi tiêm qua innerHTML.
Mike Samuel

1
@PerishableDave, tôi đồng ý rằng >sẽ được để lại trong lần thứ hai. Đó không phải là một mối nguy hiểm mặc dù. Nguy cơ xảy ra do <trái trong lần đầu tiên, điều này khiến trình phân tích cú pháp HTML ở trong một bối cảnh khác với trạng thái dữ liệu khi lần thứ hai bắt đầu. Lưu ý không có chuyển đổi từ trạng thái dữ liệu trên >.
Mike Samuel

73
@MikeSamuel Chúng tôi đã quyết định câu trả lời này chưa? Người dùng ngây thơ ở đây đã sẵn sàng để sao chép-dán.
Ziggy

1
Điều này cũng, tôi tin rằng, hoàn toàn bối rối nếu được cung cấp một cái gì đó như <button onClick="dostuff('>');"></button>Giả sử HTML được viết chính xác, bạn vẫn cần phải tính đến việc một dấu lớn hơn có thể ở đâu đó trong văn bản được trích dẫn trong một thuộc tính. Ngoài ra, bạn sẽ muốn loại bỏ tất cả các văn bản bên trong các <script>thẻ, ít nhất.
Jonathon

15
@AntonioMax, tôi đã trả lời câu hỏi quảng cáo này , nhưng với nội dung câu hỏi của bạn, bởi vì mã quan trọng bảo mật không nên được sao chép và dán. Bạn nên tải xuống một thư viện và luôn cập nhật và vá lỗi để bạn an toàn trước các lỗ hổng được phát hiện gần đây và các thay đổi trong trình duyệt.
Mike Samuel

249

Cách đơn giản nhất:

jQuery(html).text();

Điều đó lấy tất cả các văn bản từ một chuỗi html.


111
Chúng tôi luôn sử dụng jQuery cho các dự án vì các dự án của chúng tôi luôn có rất nhiều Javascript. Do đó, chúng tôi đã không thêm số lượng lớn, chúng tôi đã tận dụng mã API hiện có ...
Đánh dấu

32
Bạn sử dụng nó, nhưng OP có thể không. câu hỏi là về Javascript KHÔNG JQuery.
Mất trí

105
Đây vẫn là một câu trả lời hữu ích cho những người cần làm điều tương tự như OP (như tôi) và không ngại sử dụng jQuery (như tôi), chưa kể, nó có thể hữu ích cho OP nếu họ đang cân nhắc sử dụng jQuery. Quan điểm của trang web là chia sẻ kiến ​​thức. Hãy nhớ rằng hiệu ứng làm lạnh bạn có thể có bằng cách trừng phạt những câu trả lời hữu ích mà không có lý do chính đáng.
acjay

27
@Dementic gây sốc, tôi thấy các chủ đề có nhiều câu trả lời là hữu ích nhất, bởi vì thường thì một câu trả lời phụ đáp ứng nhu cầu chính xác của tôi, trong khi câu trả lời chính đáp ứng trường hợp chung.
Eric Goldberg

36
Điều đó sẽ không hoạt động nếu một phần của chuỗi không được bọc trong thẻ html. ví dụ: "<b> Lỗi: </ b> Vui lòng nhập email hợp lệ" sẽ chỉ trả về "Lỗi:"
Aamir Afridi

127

Tôi muốn chia sẻ một phiên bản chỉnh sửa của câu trả lời được phê duyệt của Shog9 .


Như Mike Samuel đã chỉ với một nhận xét, chức năng đó có thể thực thi mã javascript nội tuyến.
Nhưng Shog9 đã đúng khi nói "hãy để trình duyệt làm điều đó cho bạn ..."

vì vậy .. đây là phiên bản chỉnh sửa của tôi, sử dụng DOMParser :

function strip(html){
   var doc = new DOMParser().parseFromString(html, 'text/html');
   return doc.body.textContent || "";
}

đây là đoạn mã để kiểm tra javascript nội tuyến:

strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")

Ngoài ra, nó không yêu cầu tài nguyên trên phân tích cú pháp (như hình ảnh)

strip("Just text <img src='https://assets.rbl.ms/4155638/980x.jpg'>")

3
Thật đáng để thêm rằng giải pháp này chỉ hoạt động trong trình duyệt.
kris_IV

1
Đây không phải là thẻ dải, nhưng giống như PHP htmlspecialchars (). Vẫn hữu ích cho tôi.
Daantje

Lưu ý rằng điều này cũng loại bỏ khoảng trắng từ đầu văn bản.
Raine Revere

Cũng cần lưu ý, điều này không hoạt động trong Công nhân web
Chris Seufert

Đây có vẻ là nhiều nhanh hơn @ câu trả lời Shog9 của
Shmuel Kamensky

55

Là một phần mở rộng cho phương thức jQuery, nếu chuỗi của bạn có thể không chứa HTML (ví dụ: nếu bạn đang cố xóa HTML khỏi trường biểu mẫu)

jQuery(html).text();`

sẽ trả về một chuỗi rỗng nếu không có HTML

Sử dụng:

jQuery('<p>' + html + '</p>').text();

thay thế.

Cập nhật: Như đã được chỉ ra trong các bình luận, trong một số trường hợp, giải pháp này sẽ thực thi javascript có trong htmlnếu giá trị của htmlcó thể bị ảnh hưởng bởi kẻ tấn công, hãy sử dụng một giải pháp khác.


12
Hoặc$("<p>").html(html).text();
Dimitar Dimitrov

4
Điều này vẫn thực thi mã có thể nguy hiểmjQuery('<span>Text :) <img src="a" onerror="alert(1)"></span>').text()
Simon

thử jQuery ("aa & # X003c; script> alert (1) & # X003c; / script> a"). text ();
Grzegorz Kaczan

41

Chuyển đổi HTML cho gửi email văn bản thuần giữ nguyên siêu liên kết (a href)

Hàm trên được đăng bởi hypoxide hoạt động tốt, nhưng sau đó tôi đã chuyển đổi HTML được tạo trong trình soạn thảo Web RichText (ví dụ FCKEditor) và xóa tất cả HTML nhưng để lại tất cả các Liên kết do thực tế là tôi muốn cả HTML và phiên bản văn bản thuần túy để hỗ trợ tạo các phần chính xác cho email STMP (cả HTML và văn bản thuần túy).

Sau một thời gian dài tự mình tìm kiếm Google và đồng nghiệp của tôi đã tìm ra điều này bằng cách sử dụng công cụ regex trong Javascript:

str='this string has <i>html</i> code i want to <b>remove</b><br>Link Number 1 -><a href="http://www.bbc.co.uk">BBC</a> Link Number 1<br><p>Now back to normal text and stuff</p>
';
str=str.replace(/<br>/gi, "\n");
str=str.replace(/<p.*>/gi, "\n");
str=str.replace(/<a.*href="(.*?)".*>(.*?)<\/a>/gi, " $2 (Link->$1) ");
str=str.replace(/<(?:.|\s)*?>/g, "");

các strbiến bắt đầu ra như thế này:

this string has <i>html</i> code i want to <b>remove</b><br>Link Number 1 -><a href="http://www.bbc.co.uk">BBC</a> Link Number 1<br><p>Now back to normal text and stuff</p>

và sau khi mã đã chạy, nó trông như thế này: -

this string has html code i want to remove
Link Number 1 -> BBC (Link->http://www.bbc.co.uk)  Link Number 1


Now back to normal text and stuff

Như bạn có thể thấy tất cả các HTML đã bị xóa và Liên kết đã được kiên trì với văn bản siêu liên kết vẫn còn nguyên vẹn. Ngoài ra tôi đã thay thế các thẻ <p><br>bằng \n(newline char) để một số loại định dạng trực quan đã được giữ lại.

Để thay đổi định dạng liên kết (ví dụ BBC (Link->http://www.bbc.co.uk):), chỉ cần chỉnh sửa $2 (Link->$1), $1URL ở đâu / URI và $2văn bản siêu liên kết. Với các liên kết trực tiếp trong phần thân của văn bản đơn giản, hầu hết các Máy khách Mail Mail chuyển đổi chúng để người dùng có thể nhấp vào chúng.

Hy vọng bạn tìm thấy điều này hữu ích.


Nó không xử lý "& nbsp;"
Rose Nettoyeur

33

Một cải tiến cho câu trả lời được chấp nhận.

function strip(html)
{
   var tmp = document.implementation.createHTMLDocument("New").body;
   tmp.innerHTML = html;
   return tmp.textContent || tmp.innerText || "";
}

Cách này một cái gì đó chạy như thế này sẽ không có hại:

strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")

Firefox, Chromium và Explorer 9+ đều an toàn. Opera Presto vẫn dễ bị tổn thương. Ngoài ra, hình ảnh được đề cập trong chuỗi không được tải xuống trong Chromium và Firefox lưu các yêu cầu http.


Đây là một số cách, nhưng không an toàn từ<script><script>alert();
Arth

1
Điều đó không chạy bất kỳ tập lệnh nào ở đây trong Chromium / Opera / Firefox trên Linux, vậy tại sao nó không an toàn?
Janghou

Xin lỗi, tôi phải kiểm tra sai, có lẽ tôi đã quên bấm chạy lại trên jsFiddle.
Arth

Đối số "Mới" là thừa, tôi nghĩ sao?
Jon Schneider

Theo thông số kỹ thuật ngày nay nó là tùy chọn, nhưng không phải lúc nào cũng vậy.
Janghou

23

Điều này sẽ thực hiện công việc trên bất kỳ môi trường Javascript nào (bao gồm NodeJS).

const text = `
<html lang="en">
  <head>
    <style type="text/css">*{color:red}</style>
    <script>alert('hello')</script>
  </head>
  <body><b>This is some text</b><br/><body>
</html>`;

// Remove style tags and content
text.replace(/<style[^>]*>.*<\/style>/gm, '')
    // Remove script tags and content
    .replace(/<script[^>]*>.*<\/script>/gm, '')
    // Remove all opening, closing and orphan HTML tags
    .replace(/<[^>]+>/gm, '')
    // Remove leading spaces and repeated CR/LF
    .replace(/([\r\n]+ +)+/gm, '');

@pstanton bạn có thể đưa ra một ví dụ làm việc về tuyên bố của bạn?
Karl.S

3
<html><style..>* {font-family:comic-sans;}</style>Some Text</html>
pstanton

@pstanton Mình đã sửa mã và thêm bình luận, xin lỗi vì phản hồi muộn.
Karl.S

15

Tôi đã thay đổi câu trả lời của Jibberboy2000 để bao gồm một số <BR />định dạng thẻ, xóa mọi thứ bên trong <SCRIPT><STYLE>thẻ, định dạng HTML kết quả bằng cách xóa nhiều ngắt dòng và dấu cách và chuyển đổi một số mã được mã hóa HTML thành bình thường. Sau một số thử nghiệm, có vẻ như bạn có thể chuyển đổi hầu hết các trang web đầy đủ thành văn bản đơn giản trong đó tiêu đề và nội dung trang được giữ lại.

Trong ví dụ đơn giản,

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<!--comment-->

<head>

<title>This is my title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style>

    body {margin-top: 15px;}
    a { color: #D80C1F; font-weight:bold; text-decoration:none; }

</style>
</head>

<body>
    <center>
        This string has <i>html</i> code i want to <b>remove</b><br>
        In this line <a href="http://www.bbc.co.uk">BBC</a> with link is mentioned.<br/>Now back to &quot;normal text&quot; and stuff using &lt;html encoding&gt;                 
    </center>
</body>
</html>

trở thành

Đây là tiêu đề của tôi

Chuỗi này có mã html tôi muốn xóa

Trong dòng này BBC ( http://www.bbc.co.uk ) với liên kết được đề cập.

Bây giờ trở lại "văn bản bình thường" và công cụ sử dụng

Hàm thử nghiệm và trang thử nghiệm JavaScript trông như thế này:

function convertHtmlToText() {
    var inputText = document.getElementById("input").value;
    var returnText = "" + inputText;

    //-- remove BR tags and replace them with line break
    returnText=returnText.replace(/<br>/gi, "\n");
    returnText=returnText.replace(/<br\s\/>/gi, "\n");
    returnText=returnText.replace(/<br\/>/gi, "\n");

    //-- remove P and A tags but preserve what's inside of them
    returnText=returnText.replace(/<p.*>/gi, "\n");
    returnText=returnText.replace(/<a.*href="(.*?)".*>(.*?)<\/a>/gi, " $2 ($1)");

    //-- remove all inside SCRIPT and STYLE tags
    returnText=returnText.replace(/<script.*>[\w\W]{1,}(.*?)[\w\W]{1,}<\/script>/gi, "");
    returnText=returnText.replace(/<style.*>[\w\W]{1,}(.*?)[\w\W]{1,}<\/style>/gi, "");
    //-- remove all else
    returnText=returnText.replace(/<(?:.|\s)*?>/g, "");

    //-- get rid of more than 2 multiple line breaks:
    returnText=returnText.replace(/(?:(?:\r\n|\r|\n)\s*){2,}/gim, "\n\n");

    //-- get rid of more than 2 spaces:
    returnText = returnText.replace(/ +(?= )/g,'');

    //-- get rid of html-encoded characters:
    returnText=returnText.replace(/&nbsp;/gi," ");
    returnText=returnText.replace(/&amp;/gi,"&");
    returnText=returnText.replace(/&quot;/gi,'"');
    returnText=returnText.replace(/&lt;/gi,'<');
    returnText=returnText.replace(/&gt;/gi,'>');

    //-- return
    document.getElementById("output").value = returnText;
}

Nó được sử dụng với HTML này:

<textarea id="input" style="width: 400px; height: 300px;"></textarea><br />
<button onclick="convertHtmlToText()">CONVERT</button><br />
<textarea id="output" style="width: 400px; height: 300px;"></textarea><br />

1
Tôi thích giải pháp này vì nó đã xử lý các ký tự đặc biệt html ... nhưng vẫn chưa đủ gần ... chúng là câu trả lời tốt nhất cho tôi sẽ giải quyết tất cả chúng. (đó có lẽ là những gì jquery làm).
Daniel Gerson

2
Tôi nghĩ /<p.*>/ginên được /<p.*?>/gi.
cbron

Lưu ý rằng để xóa tất cả <br>các thẻ, bạn có thể sử dụng một biểu thức chính quy tốt thay vào đó: /<br\s*\/?>/theo cách đó bạn chỉ có một thay thế thay vì 3. Ngoài ra, đối với tôi, ngoại trừ việc giải mã các thực thể bạn có thể có một biểu thức chính, như thế này : /<[a-z].*?\/?>/.
Alexis Wilke

Kịch bản hay. Nhưng những gì về nội dung bảng? Mọi ý tưởng làm thế nào nó có thể được hiển thị
Hristo Enev

@DanielGerson, mã hóa html trở nên thật, rất nhanh, nhưng cách tiếp cận tốt nhất dường như là sử dụng thư viện của anh ấy
KyleMit

15
var text = html.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, "");

Đây là phiên bản regex, có khả năng phục hồi tốt hơn đối với HTML không đúng định dạng, như:

Thẻ không được tiết lộ

Some text <img

"<", ">" bên trong thuộc tính thẻ

Some text <img alt="x > y">

Dòng mới

Some <a href="http://google.com">

Mật mã

var html = '<br>This <img alt="a>b" \r\n src="a_b.gif" />is > \nmy<>< > <a>"text"</a'
var text = html.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, "");

7

Một giải pháp khác, ít được thừa nhận hơn so với nickf hoặc Shog9, sẽ là đi bộ đệ quy DOM bắt đầu từ thẻ <body> và nối thêm từng nút văn bản.

var bodyContent = document.getElementsByTagName('body')[0];
var result = appendTextNodes(bodyContent);

function appendTextNodes(element) {
    var text = '';

    // Loop through the childNodes of the passed in element
    for (var i = 0, len = element.childNodes.length; i < len; i++) {
        // Get a reference to the current child
        var node = element.childNodes[i];
        // Append the node's value if it's a text node
        if (node.nodeType == 3) {
            text += node.nodeValue;
        }
        // Recurse through the node's children, if there are any
        if (node.childNodes.length > 0) {
            appendTextNodes(node);
        }
    }
    // Return the final result
    return text;
}

3
yike. nếu bạn định tạo một cây DOM từ chuỗi của mình, thì hãy sử dụng cách của shog!
nickf

Có, giải pháp của tôi sử dụng búa tạ trong đó búa thông thường phù hợp hơn :-). Và tôi đồng ý rằng các giải pháp của bạn và Shog9 là tốt hơn, và về cơ bản đã nói rất nhiều trong câu trả lời. Tôi cũng không thể phản ánh trong phản hồi của mình rằng html đã được chứa trong một chuỗi, khiến cho câu trả lời của tôi về cơ bản là vô dụng đối với câu hỏi ban đầu. :-(
Bryan

1
Công bằng mà nói, điều này có giá trị - nếu bạn hoàn toàn phải giữ / tất cả / văn bản, thì điều này ít nhất cũng có một cơ hội tốt để nắm bắt các dòng mới, các tab, trả về vận chuyển, v.v ... Sau đó, một lần nữa, giải pháp của nickf cũng làm như vậy , và làm nhanh hơn nhiều ... eh.
Shog9

7

Nếu bạn muốn giữ các liên kết và cấu trúc của nội dung (h1, h2, v.v.) thì bạn nên kiểm tra TextVersionJS Bạn có thể sử dụng nó với bất kỳ HTML nào, mặc dù nó được tạo để chuyển đổi email HTML thành văn bản thuần túy.

Cách sử dụng rất đơn giản. Ví dụ: trong node.js:

var createTextVersion = require("textversionjs");
var yourHtml = "<h1>Your HTML</h1><ul><li>goes</li><li>here.</li></ul>";

var textVersion = createTextVersion(yourHtml);

Hoặc trong trình duyệt có js thuần:

<script src="textversion.js"></script>
<script>
  var yourHtml = "<h1>Your HTML</h1><ul><li>goes</li><li>here.</li></ul>";
  var textVersion = createTextVersion(yourHtml);
</script>

Nó cũng hoạt động với allow.js:

define(["textversionjs"], function(createTextVersion) {
  var yourHtml = "<h1>Your HTML</h1><ul><li>goes</li><li>here.</li></ul>";
  var textVersion = createTextVersion(yourHtml);
});

4

Sau khi thử tất cả các câu trả lời được đề cập nhiều nhất nếu không phải tất cả chúng đều có trường hợp cạnh và không thể hoàn toàn hỗ trợ nhu cầu của tôi.

Tôi đã bắt đầu khám phá cách php thực hiện nó và tình cờ thấy lib php.js sao chép phương thức Strip_tags tại đây: http://phpjs.org/fifts/strip_tags/


Đây là một chức năng gọn gàng và tài liệu tốt. Tuy nhiên, nó có thể được thực hiện nhanh hơn khi allowed == ''tôi nghĩ đó là những gì OP yêu cầu, gần như những gì Byron đã trả lời dưới đây (Byron chỉ nhận [^>]sai.)
Alexis Wilke

1
Nếu bạn sử dụng thông số allowedbạn dễ bị XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')trả về<p onclick="alert(1)">mytext</p>
Chris Cinelli

4
function stripHTML(my_string){
    var charArr   = my_string.split(''),
        resultArr = [],
        htmlZone  = 0,
        quoteZone = 0;
    for( x=0; x < charArr.length; x++ ){
     switch( charArr[x] + htmlZone + quoteZone ){
       case "<00" : htmlZone  = 1;break;
       case ">10" : htmlZone  = 0;resultArr.push(' ');break;
       case '"10' : quoteZone = 1;break;
       case "'10" : quoteZone = 2;break;
       case '"11' : 
       case "'12" : quoteZone = 0;break;
       default    : if(!htmlZone){ resultArr.push(charArr[x]); }
     }
    }
    return resultArr.join('');
}

Tài khoản cho> bên trong thuộc tính và <img onerror="javascript">trong các yếu tố dom mới được tạo.

sử dụng:

clean_string = stripHTML("string with <html> in it")

bản giới thiệu:

https://jsfiddle.net/gaby_de_wilde/pqayphzd/

bản demo của câu trả lời hàng đầu làm những điều khủng khiếp:

https://jsfiddle.net/gaby_de_wilde/6f0jymL6/1/


Bạn cũng sẽ cần xử lý các trích dẫn đã thoát trong một giá trị thuộc tính (ví dụ string with <a malicious="attribute \">this text should be removed, but is not">example</a>).
Pickup Logan

4

Rất nhiều người đã trả lời điều này rồi, nhưng tôi nghĩ có thể hữu ích khi chia sẻ chức năng tôi đã viết để tách các thẻ HTML từ một chuỗi nhưng cho phép bạn bao gồm một loạt các thẻ mà bạn không muốn bị tước. Nó khá ngắn và đã làm việc tốt cho tôi.

function removeTags(string, array){
  return array ? string.split("<").filter(function(val){ return f(array, val); }).map(function(val){ return f(array, val); }).join("") : string.split("<").map(function(d){ return d.split(">").pop(); }).join("");
  function f(array, value){
    return array.map(function(d){ return value.includes(d + ">"); }).indexOf(true) != -1 ? "<" + value : value.split(">")[1];
  }
}

var x = "<span><i>Hello</i> <b>world</b>!</span>";
console.log(removeTags(x)); // Hello world!
console.log(removeTags(x, ["span", "i"])); // <span><i>Hello</i> world!</span>

3

Tôi nghĩ cách dễ nhất là chỉ sử dụng Biểu thức chính quy như ai đó đã đề cập ở trên. Mặc dù không có lý do để sử dụng một loạt chúng. Thử:

stringWithHTML = stringWithHTML.replace(/<\/?[a-z][a-z0-9]*[^<>]*>/ig, "");

11
Đừng làm điều này nếu bạn quan tâm đến bảo mật. Nếu đầu vào của người dùng là: '<Scr <script> ipt> alert (42); </ Scr </ script> ipt>' thì phiên bản bị tước sẽ là: '<script> alert (42); </ script > '. Vì vậy, đây là một lỗ hổng XSS.
molnarg

Bạn nên thay đổi [^<>]bằng [^>]vì một thẻ hợp lệ không thể bao gồm một <ký tự, sau đó lỗ hổng XSS biến mất.
Alexis Wilke

3

Tôi đã thực hiện một số sửa đổi cho tập lệnh Jibberboy2000 ban đầu Hy vọng nó sẽ hữu ích cho ai đó

str = '**ANY HTML CONTENT HERE**';

str=str.replace(/<\s*br\/*>/gi, "\n");
str=str.replace(/<\s*a.*href="(.*?)".*>(.*?)<\/a>/gi, " $2 (Link->$1) ");
str=str.replace(/<\s*\/*.+?>/ig, "\n");
str=str.replace(/ {2,}/gi, " ");
str=str.replace(/\n+\s*/gi, "\n\n");

3

Đây là phiên bản sắp xếp giải quyết vấn đề bảo mật của @ MikeSamuel:

function strip(html)
{
   try {
       var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null);
       doc.documentElement.innerHTML = html;
       return doc.documentElement.textContent||doc.documentElement.innerText;
   } catch(e) {
       return "";
   }
}

Lưu ý, nó sẽ trả về một chuỗi trống nếu đánh dấu HTML không hợp lệ XML (hay còn gọi là các thẻ phải được đóng và các thuộc tính phải được trích dẫn). Điều này không lý tưởng, nhưng tránh được vấn đề có tiềm năng khai thác bảo mật.

Nếu không có đánh dấu XML hợp lệ là một yêu cầu đối với bạn, bạn có thể thử sử dụng:

var doc = document.implementation.createHTMLDocument("");

nhưng đó không phải là một giải pháp hoàn hảo cho các lý do khác.


Điều đó sẽ thất bại trong nhiều trường hợp nếu văn bản đến từ đầu vào của người dùng (textarea hoặc widget có thể di chuyển được ...)
Alexis Wilke

3

Bạn có thể tách các thẻ html một cách an toàn bằng cách sử dụng thuộc tính hộp cát iframe .

Ý tưởng ở đây là thay vì cố gắng lấy lại chuỗi của chúng tôi, chúng tôi tận dụng trình phân tích cú pháp riêng của trình duyệt bằng cách chèn văn bản vào một phần tử DOM và sau đó truy vấn textContent/ innerTextthuộc tính của phần tử đó.

Phần tử phù hợp nhất để chèn văn bản của chúng tôi là iframe được đóng hộp cát, theo cách đó chúng tôi có thể ngăn chặn mọi thực thi mã tùy ý (Còn được gọi là XSS ).

Nhược điểm của phương pháp này là nó chỉ hoạt động trong trình duyệt.

Đây là những gì tôi nghĩ ra (Không phải thử nghiệm chiến đấu):

const stripHtmlTags = (() => {
  const sandbox = document.createElement("iframe");
  sandbox.sandbox = "allow-same-origin"; // <--- This is the key
  sandbox.style.setProperty("display", "none", "important");

  // Inject the sanbox in the current document
  document.body.appendChild(sandbox);

  // Get the sandbox's context
  const sanboxContext = sandbox.contentWindow.document;

  return (untrustedString) => {
    if (typeof untrustedString !== "string") return ""; 

    // Write the untrusted string in the iframe's body
    sanboxContext.open();
    sanboxContext.write(untrustedString);
    sanboxContext.close();

    // Get the string without html
    return sanboxContext.body.textContent || sanboxContext.body.innerText || "";
  };
})();

Cách sử dụng ( bản demo ):

console.log(stripHtmlTags(`<img onerror='alert("could run arbitrary JS here")' src='bogus'>XSS injection :)`));
console.log(stripHtmlTags(`<script>alert("awdawd");</` + `script>Script tag injection :)`));
console.log(stripHtmlTags(`<strong>I am bold text</strong>`));
console.log(stripHtmlTags(`<html>I'm a HTML tag</html>`));
console.log(stripHtmlTags(`<body>I'm a body tag</body>`));
console.log(stripHtmlTags(`<head>I'm a head tag</head>`));
console.log(stripHtmlTags(null));

Giải pháp tuyệt vời cho môi trường dựa trên web! Có lẽ bạn không nên sử dụng IIFE vì kể từ ECMAScript 2015, các biến trong phạm vi khối đã được sắp xếp đúng khối với các toán tử letconsttoán tử. Ngoài ra, sử dụng giải pháp của bạn, tôi có rất nhiều tài liệu tham khảo iframeskhông được sử dụng trong tài liệu. Xem xét thêm một document.body.removeChild(sandbox)mã trong các độc giả dựa trên bản sao trong tương lai.
Amin NAIRI

2

Với jQuery, bạn có thể lấy nó bằng cách sử dụng

$('#elementID').text()

2

Mã bên dưới cho phép bạn giữ lại một số thẻ html trong khi tước tất cả các thẻ khác

function strip_tags(input, allowed) {

  allowed = (((allowed || '') + '')
    .toLowerCase()
    .match(/<[a-z][a-z0-9]*>/g) || [])
    .join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)

  var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
      commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;

  return input.replace(commentsAndPhpTags, '')
      .replace(tags, function($0, $1) {
          return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
      });
}

1
Bạn nên trích dẫn nguồn ( phpjs). Nếu bạn sử dụng thông số allowedbạn dễ bị XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')trả về<p onclick="alert(1)">mytext</p>
Chris Cinelli

2

Cũng có thể sử dụng trình phân tích cú pháp JS HTML thuần htmlparser2 . Đây là một bản demo làm việc:

var htmlparser = require('htmlparser2');

var body = '<p><div>This is </div>a <span>simple </span> <img src="test"></img>example.</p>';

var result = [];

var parser = new htmlparser.Parser({
    ontext: function(text){
        result.push(text);
    }
}, {decodeEntities: true});

parser.write(body);
parser.end();

result.join('');

Đầu ra sẽ là This is a simple example.

Xem nó trong hành động ở đây: https://tonicdev.com/jfahrenkrug/extract-text-from-html

Điều này hoạt động trong cả nút và trình duyệt nếu bạn đóng gói ứng dụng web của mình bằng công cụ như webpack.


2

Tôi chỉ cần loại bỏ các <a>thẻ và thay thế chúng bằng văn bản của liên kết.

Điều này dường như làm việc tuyệt vời.

htmlContent= htmlContent.replace(/<a.*href="(.*?)">/g, '');
htmlContent= htmlContent.replace(/<\/a>/g, '');

Điều này chỉ áp dụng cho một thẻ và cần điều chỉnh để trở thành một chức năng rộng.
m3nda

Vâng, cộng với một thẻ neo có thể có nhiều thuộc tính khác như title="...".
Alexis Wilke


1

Tôi đã tự tạo một biểu thức làm việc đều đặn:

str=str.replace(/(<\?[a-z]*(\s[^>]*)?\?(>|$)|<!\[[a-z]*\[|\]\]>|<!DOCTYPE[^>]*?(>|$)|<!--[\s\S]*?(-->|$)|<[a-z?!\/]([a-z0-9_:.])*(\s[^>]*)?(>|$))/gi, ''); 

1

jquery 2 dòng đơn giản để dải html.

 var content = "<p>checking the html source&nbsp;</p><p>&nbsp;
  </p><p>with&nbsp;</p><p>all</p><p>the html&nbsp;</p><p>content</p>";

 var text = $(content).text();//It gets you the plain text
 console.log(text);//check the data in your console

 cj("#text_area_id").val(text);//set your content to text area using text_area_id

1

Câu trả lời được chấp nhận hoạt động tốt, tuy nhiên trong IE nếu htmlchuỗi là nullbạn nhận được "null"(thay vì ''). Đã sửa:

function strip(html)
{
   if (html == null) return "";
   var tmp = document.createElement("DIV");
   tmp.innerHTML = html;
   return tmp.textContent || tmp.innerText || "";
}

1

Sử dụng Jquery:

function stripTags() {
    return $('<p></p>').html(textToEscape).text()
}

1

inputphần tử chỉ hỗ trợ một dòng văn bản :

Trạng thái văn bản thể hiện điều khiển chỉnh sửa văn bản thuần một dòng cho giá trị của phần tử.

function stripHtml(str) {
  var tmp = document.createElement('input');
  tmp.value = str;
  return tmp.value;
}

Cập nhật: điều này hoạt động như mong đợi

function stripHtml(str) {
  // Remove some tags
  str = str.replace(/<[^>]+>/gim, '');

  // Remove BB code
  str = str.replace(/\[(\w+)[^\]]*](.*?)\[\/\1]/g, '$2 ');

  // Remove html and line breaks
  const div = document.createElement('div');
  div.innerHTML = str;

  const input = document.createElement('input');
  input.value = div.textContent || div.innerText || '';

  return input.value;
}

Không hoạt động, vui lòng luôn đề cập đến trình duyệt bạn đang sử dụng khi đăng câu trả lời. Điều này không chính xác và sẽ không hoạt động trong Chrome 61. Thẻ chỉ được hiển thị dưới dạng chuỗi.
vdegenne

0
    (function($){
        $.html2text = function(html) {
            if($('#scratch_pad').length === 0) {
                $('<div id="lh_scratch"></div>').appendTo('body');  
            }
            return $('#scratch_pad').html(html).text();
        };

    })(jQuery);

Xác định đây là một plugin jquery và sử dụng nó như sau:

$.html2text(htmlContent);

Hãy nói rằng điều này đến từ đầu vào của người dùng. Nó có thể được sử dụng để thêm tập lệnh hoặc macro vào trang của bạn
Oluwatumbi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.