Câu trả lời:
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 .
strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")
myString.replace(/<[^>]*>?/gm, '');
<img src=http://www.google.com.kh/images/srpr/nav_logo27.png onload="alert(42)"
nếu bạn tiêm qua document.write
hoặc nối với một chuỗi có chứa >
trước khi tiêm qua innerHTML
.
>
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 >
.
<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.
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.
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'>")
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 html
nếu giá trị của html
có 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.
$("<p>").html(html).text();
jQuery('<span>Text :) <img src="a" onerror="alert(1)"></span>').text()
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 str
biế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>
và <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)
, $1
URL ở đâu / URI và $2
vă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.
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.
<script><script>alert();
Đ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, '');
<html><style..>* {font-family:comic-sans;}</style>Some Text</html>
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>
và <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 "normal text" and stuff using <html encoding>
</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(/ /gi," ");
returnText=returnText.replace(/&/gi,"&");
returnText=returnText.replace(/"/gi,'"');
returnText=returnText.replace(/</gi,'<');
returnText=returnText.replace(/>/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 />
/<p.*>/gi
nên được /<p.*?>/gi
.
<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].*?\/?>/
.
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, "");
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;
}
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);
});
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/
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.)
allowed
bạn dễ bị XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')
trả về<p onclick="alert(1)">mytext</p>
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:
string with <a malicious="attribute \">this text should be removed, but is not">example</a>
).
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>
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, "");
[^<>]
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.
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");
Đâ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.
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
/ innerText
thuộ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));
let
và const
toá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 iframes
khô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.
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 : '';
});
}
phpjs
). Nếu bạn sử dụng thông số allowed
bạn dễ bị XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')
trả về<p onclick="alert(1)">mytext</p>
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.
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, '');
title="..."
.
Để có giải pháp dễ dàng hơn, hãy thử điều này => https://css-tricks.com/snippets/javascript/strip-html-tags-in-javascript/
var StrippedString = OriginalString.replace(/(<([^>]+)>)/ig,"");
jquery 2 dòng đơn giản để dải html.
var content = "<p>checking the html source </p><p>
</p><p>with </p><p>all</p><p>the html </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
Câu trả lời được chấp nhận hoạt động tốt, tuy nhiên trong IE nếu html
chuỗi là null
bạ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 || "";
}
input
phầ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;
}
(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);