Декодирование и возврат к & в JavaScript
У меня есть строки типа
var str = 'One & two & three';
отображаемый в HTML веб-сервером. Мне нужно преобразовать эти строки в
'One & two & three'
В настоящее время это то, что я делаю (с помощью jQuery):
$(document.createElement('div')).html('{{ driver.person.name }}').text()
Однако у меня есть тревожное ощущение, что я делаю это неправильно.
Я пробовал
unescape("&")
но, похоже, он не работает, и decodeURI/decodeURIComponent.
Есть ли другие, более родные и элегантные способы сделать это?
Ответы
Ответ 1
Более современный вариант для интерпретации HTML (текст и прочее) из JavaScript - это поддержка HTML в API DOMParser
(см. здесь в MDN). Это позволяет использовать собственный HTML-парсер браузера для преобразования строки в HTML-документ. Он поддерживается в новых версиях всех основных браузеров с конца 2014 года.
Если мы просто хотим декодировать некоторый текстовый контент, мы можем поместить его как единственный контент в тело документа, проанализировать документ и вытащить его .body.textContent
.
var encodedStr = 'hello & world';
var parser = new DOMParser;
var dom = parser.parseFromString(
'<!doctype html><body>' + encodedStr,
'text/html');
var decodedString = dom.body.textContent;
console.log(decodedString);
Ответ 2
Вам нужно декодировать все закодированные объекты HTML или просто &
самостоятельно?
Если вам нужно обработать только &
, вы можете сделать это:
var decoded = encoded.replace(/&/g, '&');
Если вам нужно декодировать все объекты HTML, вы можете сделать это без jQuery:
var elem = document.createElement('textarea');
elem.innerHTML = encoded;
var decoded = elem.value;
Пожалуйста, обратите внимание на комментарии Mark ниже, в которых выделяются дыры в безопасности в более ранней версии этого ответа и рекомендуется использовать textarea
вместо div
для смягчения возможных уязвимостей XSS. Эти уязвимости существуют, если вы используете jQuery или обычный JavaScript.
Ответ 3
У Матиаса Биненса есть библиотека для этого: https://github.com/mathiasbynens/he
Пример:
console.log(
he.decode("Jörg & Jürgen rocked to & fro ")
);
// Logs "Jörg & Jürgen rocked to & fro"
Я предлагаю отдать ему предпочтение перед взломами, включающими установку HTML-содержимого элемента и последующее чтение его текстового содержимого. Такие подходы могут работать, но они обманчиво опасны и представляют возможности XSS, если они используются для ненадежного пользовательского ввода.
Если вы действительно не можете загрузить библиотеку, вы можете использовать хак textarea
описанный в этом ответе, для почти дублированного вопроса, который, в отличие от предложенных различных похожих подходов, не имеет дыр в безопасности, о которых я знаю:
function decodeEntities(encodedString) {
var textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}
console.log(decodeEntities('1 & 2')); // '1 & 2'
Но обратите внимание на проблемы безопасности, затрагивающие сходные подходы к этому, которые я перечислю в связанном ответе! Этот подход является хакерским, и будущие изменения в допустимом содержимом textarea
(или ошибок в определенных браузерах) могут привести к тому, что код, который полагается на него, однажды вдруг обнаружит дыру в XSS.
Ответ 4
var htmlEnDeCode = (function() {
var charToEntityRegex,
entityToCharRegex,
charToEntity,
entityToChar;
function resetCharacterEntities() {
charToEntity = {};
entityToChar = {};
// add the default set
addCharacterEntities({
'&' : '&',
'>' : '>',
'<' : '<',
'"' : '"',
''' : "'"
});
}
function addCharacterEntities(newEntities) {
var charKeys = [],
entityKeys = [],
key, echar;
for (key in newEntities) {
echar = newEntities[key];
entityToChar[key] = echar;
charToEntity[echar] = key;
charKeys.push(echar);
entityKeys.push(key);
}
charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
}
function htmlEncode(value){
var htmlEncodeReplaceFn = function(match, capture) {
return charToEntity[capture];
};
return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
}
function htmlDecode(value) {
var htmlDecodeReplaceFn = function(match, capture) {
return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
};
return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
}
resetCharacterEntities();
return {
htmlEncode: htmlEncode,
htmlDecode: htmlDecode
};
})();
Это из исходного кода ExtJS.
Ответ 5
element.innerText
также выполняет трюк.
Ответ 6
В случае, если вы ищете его, как я - тем временем есть хороший и безопасный метод JQuery.
https://api.jquery.com/jquery.parsehtml/
Вы можете, например, введите это в вашей консоли:
var x = "test &";
> undefined
$.parseHTML(x)[0].textContent
> "test &"
Таким образом, $.parseHTML(x) возвращает массив, и если в вашем тексте есть разметка HTML, то значение array.length будет больше 1.
Ответ 7
jQuery будет кодироваться и декодироваться для вас. Однако вам нужно использовать тег textarea, а не div.
var str1 = 'One & two & three';
var str2 = "One & two & three";
$(document).ready(function() {
$("#encoded").text(htmlEncode(str1));
$("#decoded").text(htmlDecode(str2));
});
function htmlDecode(value) {
return $("<textarea/>").html(value).text();
}
function htmlEncode(value) {
return $('<textarea/>').text(value).html();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="encoded"></div>
<div id="decoded"></div>
Ответ 8
Сначала создайте <span id="decodeIt" style="display:none;"></span>
где-нибудь в теле
Затем назначьте строку, которая будет декодирована как innerHTML, на это:
document.getElementById("decodeIt").innerHTML=stringtodecode
Наконец,
stringtodecode=document.getElementById("decodeIt").innerText
Вот общий код:
var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText
Ответ 9
Для однострочных парней:
const htmlDecode = innerHTML => Object.assign(document.createElement('textarea'), {innerHTML}).value;
console.log(htmlDecode('Complicated - Dimitri Vegas & Like Mike'));
Ответ 10
Вы можете использовать функцию unescape/escape Lodash https://lodash.com/docs/4.17.5#unescape
import unescape from 'lodash/unescape';
const str = unescape('fred, barney, & pebbles');
ул станет 'fred, barney, & pebbles'
Ответ 11
javascript-решение, которое ловит общие:
var map = {amp: '&', lt: '<', gt: '>', quot: '"', '#039': "'"}
str = str.replace(/&([^;]+);/g, (m, c) => map[c])
это обратная сторона fooobar.com/questions/21522/...
Ответ 12
Я обнаружил, что иногда вам не нужно кодировать и декодировать, если вы ограничиваете набор символов, добавляя следующий мета-атрибут.
<meta charset="UTF-8">
Ответ 13
Я пытался все, чтобы удалить & из массива JSON. Ни один из приведенных выше примеров, но https://stackoverflow.com/users/2030321/chris не дал отличного решения, которое привело меня к решению моей проблемы.
var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText
Я не использовал, потому что я не понимал, как вставить его в модальное окно, которое вытягивало данные JSON в массив, но я попробовал это на основе примера, и это сработало:
var modal = document.getElementById('demodal');
$('#ampersandcontent').text(replaceAll(data[0],"&", "&"));
Мне нравится это, потому что это было просто, и это работает, но не уверен, почему это не широко используется. Искал привет и низ, чтобы найти простое решение. Я продолжаю искать понимание синтаксиса и есть ли риск его использования. Пока не нашли ничего.