2010-06-15 3 views
3

У меня есть строка, которая содержит текст HTML. Мне нужно избегать строк, а не тегов. Например, у меня есть строка, которая содержит,Как избежать HTML

<ul class="main_nav"> 
<li> 
<a class="className1" id="idValue1" tabindex="2">Test & Sample</a> 
</li> 
<li> 
<a class="className2" id="idValue2" tabindex="2">Test & Sample2</a> 
</li> 
</ul> 

Как избежать только текст,

<ul class="main_nav"> 
<li> 
<a class="className1" id="idValue1" tabindex="2">Test &amp; Sample</a> 
</li> 
<li> 
<a class="className2" id="idValue2" tabindex="2">Test &amp; Sample2</a> 
</li> 
</ul> 

с из модифицирующих тегов.

Можно ли это обрабатывать с помощью HTML DOM и javascript?

Благодаря

+4

каким образом строки генерируются? – matpol

+1

Можете ли вы установить '.innerText' ваших якорей - я думаю, что непослушные символы исчезают. – James

ответ

8

(см дальше вниз для ответа на вопрос, как актуализация комментарии из ниже OP)

Может ли это быть обработаны с HTML DOM и JavaScript?

Нет, как только текст находится в DOM, концепция «экранирования» не применяется. HTML Исходный текст должен быть экранирован так, чтобы он правильно разбирался в DOM; как только он находится в DOM, он не сбежит.

Это может быть немного сложно понять, поэтому давайте использовать пример. Вот некоторые HTML исходный текст (например, в HTML-файл, который будет просматривать с помощью браузера):

<div>This &amp; That</div> 

Как только это будет проанализирован в DOM с помощью браузера, текст внутри DIV является This & That, потому что &amp; был истолкован в этом пункте.

Итак, вам нужно поймать это раньше, прежде чем текст будет разобран в DOM браузером. После этого вы не сможете справиться, уже слишком поздно.

Отдельно, строка, с которой вы начинаете, недействительна, если в ней есть такие вещи, как <div>This & That</div>. Предварительная обработка этой недопустимой строки будет сложной. Вы не можете просто использовать встроенные функции вашей среды (PHP или что-то еще, что вы используете на стороне сервера), потому что они также избегают этих тегов. Вам нужно будет выполнить обработку текста, извлекая только те части, которые вы хотите обработать, а затем выполните их с помощью процесса экранирования. Этот процесс будет сложным. &, за которым следуют пробелы, достаточно просто, но если в исходном тексте есть неэквивалентные объекты, как вы знаете, следует ли их избегать или нет? Вы предполагаете, что если строка содержит &amp;, вы оставите ее в покое? Или превратить его в &amp;amp;? (Что совершенно верно, так вы показываете фактическую строку &amp; на странице HTML.)

Что вам действительно нужно сделать, это исправить основную проблему: вещь, создающая эти недопустимые, полукодированные строки.


Редактировать: Из нашего комментария потока ниже, вопрос совершенно иначе, чем это казалось из вашего примера (это не означает, критически).Чтобы повторить комментарии для тех, кто пришел к этому, вы сказали, что получаете эти строки из innerHTML от WebKit, и я сказал, что это было нечетно, innerHTML должен правильно закодировать & (и указал вам на из test pages, что и предполагалось). Ваш ответ был:

Это работает для &. Но одна и та же тестовая страница не работает для таких объектов, как ©, ®, « и многие другие.

Это изменяет характер вопроса. Вы хотите сделать сущности из символов, которые, будучи совершенно правильными, когда они используются буквально (при условии, что у вас есть правильное кодирование текста), могут быть выражены как сущности вместо этого и, следовательно, более устойчивы к изменениям текстового кодирования.

Мы можем это сделать. Согласно the spec значения символов в строке JavaScript составляют UTF-16 (с использованием Unicode Normalized Form C), и любое преобразование из кодировки исходного кода (ISO 8859-1, Windows-1252, UTF-8, независимо) выполняется до того, как среда выполнения JavaScript увидит это. (Если вы не на 100% уверены, что знаете, что я имею в виду под кодировкой символов, стоит остановиться сейчас, уйдя и прочитав от Joel Spolsky, затем вернувшись.) Итак, это входная сторона. На стороне вывода объекты HTML идентифицируют точки кода Unicode. Таким образом, мы можем надежно преобразовать из строк JavaScript в объекты HTML.

Дьявол в деталях, хотя, как всегда. JavaScript явно предполагает, что каждое 16-битовое значение является символом (см. Раздел 8.4 в спецификации), хотя на самом деле это неверно для UTF-16   —. Одно 16-битное значение может быть «суррогатным» (например, 0xD800), которое имеет смысл только в сочетании со следующим значением, что означает, что два «символа» в строке JavaScript на самом деле являются одним символом. Это не редкость для дальневосточных языков.

Так надежное преобразование, которое начинается со строки JavaScript и приводит к тому, что объект HTML не может считать, что символ «JavaScript» фактически равен символу в тексте, он должен обрабатывать суррогаты. К счастью, делать это легко, потому что умные люди, определяющие Unicode, сделали его мертвым: первое суррогатное значение всегда находится в диапазоне 0xD800-0xDBFF (включительно), а второй суррогат всегда находится в диапазоне 0xDC00-0xDFFF (включительно). Поэтому в любое время, когда вы видите пару «символов» в строке JavaScript, которые соответствуют этим диапазонам, вы имеете дело с одним символом, определенным суррогатной парой. Формулы для преобразования из пары суррогатных значений в значение кодовой точки приведены в приведенных выше ссылках, хотя и довольно тупо; Я нахожу this page гораздо более доступным.

Вооружившись всей этой информацией, мы можем написать функцию, которая возьмет строку JavaScript и будет искать символы (реальные символы, которые могут быть длиной один или два символа), вы можете захотеть превратиться в сущности, заменив их именованные объектные сущности из карты или числовых лиц, если мы не имеем их в нашем имени карты:

// A map of the entities we want to handle. 
// The numbers on the left are the Unicode code point values; their 
// matching named entity strings are on the right. 
var entityMap = { 
    "160": "&nbsp;", 
    "161": "&iexcl;", 
    "162": "&#cent;", 
    "163": "&#pound;", 
    "164": "&#curren;", 
    "165": "&#yen;", 
    "166": "&#brvbar;", 
    "167": "&#sect;", 
    "168": "&#uml;", 
    "169": "&copy;", 
    // ...and lots and lots more, see http://www.w3.org/TR/REC-html40/sgml/entities.html 
    "8364": "&euro;" // Last one must not have a comma after it, IE doesn't like trailing commas 
}; 

// The function to do the work. 
// Accepts a string, returns a string with replacements made. 
function prepEntities(str) { 
    // The regular expression below uses an alternation to look for a surrogate pair _or_ 
    // a single character that we might want to make an entity out of. The first part of the 
    // alternation (the [\uD800-\uDBFF][\uDC00-\uDFFF] before the |), you want to leave 
    // alone, it searches for the surrogates. The second part of the alternation you can 
    // adjust as you see fit, depending on how conservative you want to be. The example 
    // below uses [\u0000-\u001f\u0080-\uFFFF], meaning that it will match and convert any 
    // character with a value from 0 to 31 ("control characters") or above 127 -- e.g., if 
    // it's not "printable ASCII" (in the old parlance), convert it. That's probably 
    // overkill, but you said you wanted to make entities out of things, so... :-) 
    return str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u0000-\u001f\u0080-\uFFFF]/g, function(match) { 
     var high, low, charValue, rep 

     // Get the character value, handling surrogate pairs 
     if (match.length == 2) { 
      // It's a surrogate pair, calculate the Unicode code point 
      high = match.charCodeAt(0) - 0xD800; 
      low = match.charCodeAt(1) - 0xDC00; 
      charValue = (high * 0x400) + low + 0x10000; 
     } 
     else { 
      // Not a surrogate pair, the value *is* the Unicode code point 
      charValue = match.charCodeAt(0); 
     } 

     // See if we have a mapping for it 
     rep = entityMap[charValue]; 
     if (!rep) { 
      // No, use a numeric entity. Here we brazenly (and possibly mistakenly) 
      rep = "&#" + charValue + ";"; 
     } 

     // Return replacement 
     return rep; 
    }); 
} 

Вы должны быть хорошо передавая все HTML через него, так как, если эти символы появляются в значениях атрибутов, вы почти наверняка хотите их закодировать там.

У меня не используется выше в производстве (я на самом деле написал для этого ответа, потому что проблема заинтриговала меня), и это полностью поставляется без гарантийного любого вида.Я пытался обеспечить, чтобы он обрабатывал суррогатные пары, потому что это необходимо для дальневосточных языков, и поддержка их - это то, что мы все должны делать сейчас, когда мир стал меньше.

Полный пример страницы:

<!DOCTYPE HTML> 
<html> 
<head> 
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"> 
<title>Test Page</title> 
<style type='text/css'> 
body { 
    font-family: sans-serif; 
} 
#log p { 
    margin:  0; 
    padding: 0; 
} 
</style> 
<script type='text/javascript'> 

// Make the function available as a global, but define it within a scoping 
// function so we can have data (the `entityMap`) that only it has access to 
var prepEntities = (function() { 

    // A map of the entities we want to handle. 
    // The numbers on the left are the Unicode code point values; their 
    // matching named entity strings are on the right. 
    var entityMap = { 
     "160": "&nbsp;", 
     "161": "&iexcl;", 
     "162": "&#cent;", 
     "163": "&#pound;", 
     "164": "&#curren;", 
     "165": "&#yen;", 
     "166": "&#brvbar;", 
     "167": "&#sect;", 
     "168": "&#uml;", 
     "169": "&copy;", 
     // ...and lots and lots more, see http://www.w3.org/TR/REC-html40/sgml/entities.html 
     "8364": "&euro;" // Last one must not have a comma after it, IE doesn't like trailing commas 
    }; 

    // The function to do the work. 
    // Accepts a string, returns a string with replacements made. 
    function prepEntities(str) { 
     // The regular expression below uses an alternation to look for a surrogate pair _or_ 
     // a single character that we might want to make an entity out of. The first part of the 
     // alternation (the [\uD800-\uDBFF][\uDC00-\uDFFF] before the |), you want to leave 
     // alone, it searches for the surrogates. The second part of the alternation you can 
     // adjust as you see fit, depending on how conservative you want to be. The example 
     // below uses [\u0000-\u001f\u0080-\uFFFF], meaning that it will match and convert any 
     // character with a value from 0 to 31 ("control characters") or above 127 -- e.g., if 
     // it's not "printable ASCII" (in the old parlance), convert it. That's probably 
     // overkill, but you said you wanted to make entities out of things, so... :-) 
     return str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u0000-\u001f\u0080-\uFFFF]/g, function(match) { 
      var high, low, charValue, rep 

      // Get the character value, handling surrogate pairs 
      if (match.length == 2) { 
       // It's a surrogate pair, calculate the Unicode code point 
       high = match.charCodeAt(0) - 0xD800; 
       low = match.charCodeAt(1) - 0xDC00; 
       charValue = (high * 0x400) + low + 0x10000; 
      } 
      else { 
       // Not a surrogate pair, the value *is* the Unicode code point 
       charValue = match.charCodeAt(0); 
      } 

      // See if we have a mapping for it 
      rep = entityMap[charValue]; 
      if (!rep) { 
       // No, use a numeric entity. Here we brazenly (and possibly mistakenly) 
       rep = "&#" + charValue + ";"; 
      } 

      // Return replacement 
      return rep; 
     }); 
    } 

    // Return the function reference out of the scoping function to publish it 
    return prepEntities; 
})(); 

function go() { 
    var d = document.getElementById('d1'); 
    var s = d.innerHTML; 
    alert("Before: " + s); 
    s = prepEntities(s); 
    alert("After: " + s); 
} 

</script> 
</head> 
<body> 
<div id='d1'>Copyright: &copy; Yen: &yen; Cedilla: &cedil; Surrogate pair: &#65536;</div> 
<input type='button' id='btnGo' value='Go' onclick="return go();"> 
</body> 
</html> 

Там я включил седиль как пример преобразования в цифровой сущности, а не по имени одного (так как я покинул cedil из моей очень небольшой пример карты). И обратите внимание, что суррогатная пара в конце появляется в первом предупреждении как два «символа» из-за того, как JavaScript обрабатывает UTF-16.

+0

@ T.J. Crowder: Спасибо за объяснение. Позвольте мне подробно рассказать о моей конкретной проблеме. Я хочу сохранить исходный файл HTML на диск. И я попытался получить контент, используя, document.childNodes [i] .outerHTML; а также document.getElementsByTagName ('html') [0] .innerHTML; Некоторые из объектов будут декодированы DOM. Я хочу сохранить объекты как оригинальные. Я не знаю альтернативного подхода, чтобы получить содержимое html (при сохранении текущего состояния) и сохранить объекты. Я использую QT webkit и javascript. Любая помощь в этом отношении. Спасибо – kokila

+0

@kokila: Если вы используете 'innerHTML' или' outerHTML' для получения строк из WebKit, они должны быть уже правильно экранированы. Эта тестовая страница (http://pastie.org/1005105) дает ожидаемый результат как в Chrome, так и в Safari (браузеры на базе WebKit).Даже если я дам им недопустимый HTML-файл, используя '&' вместо '&' (http://pastie.org/1005109), они исправляют его во время синтаксического анализа и дают мне версию сущности при восстановлении HTML для 'innerHTML' и 'outerHTML'. –

+0

@ T.J. Crowder: Это работает для &. Но одна и та же тестовая страница не работает для таких объектов, как ©, ®, « и многие другие. Пример

Testing this © that
. У меня точно такая же проблема. – kokila

-1

Какой серверный язык вы используете?

если вы используете PHP, вы можете использовать htmlentities

Пример:

<?php 

$myHTML = "<h1>Some HTML Tags</h1><br />"; 
echo htmlentities($myHTML); 

?> 
+1

Нет, это также позволит избежать тегов. ОП сказал, что он хочет избежать только бит * между * тегами (очень сложная и подверженная ошибкам операция). –

+0

Вопрос помечен 'javascript'. Нет никаких указаний на то, что любой язык на стороне сервера вообще задействован. – Quentin

-2

ли вы пытались бежать функцию() в JavaScript? JavaScript escape() Function

+2

Эта функция была создана для экранирования параметров URL, а не HTML. И даже в параметрах URL-адреса это неправильно. – Tomalak

+1

@Tomalek: 'escape' не был специально для экранирования параметров URL-адреса (он не кодирует URL-адреса), это было просто для того, чтобы избежать передачи данных как часть GET или POST в конкретный, хорошо контролируемый формат (отличается от URL-кодирования). И да, это абсолютно не имеет никакого отношения к экранированию HTML. –

8

Я очень удивлен, что никто не ответил на это. Вы можете просто использовать браузер самостоятельно, чтобы выполнить эвакуацию для вас. Нет регулярного выражения лучше или безопаснее, чем позволить браузеру делать то, что он делает лучше всего, обрабатывать HTML.

function escapeHTML(str){ 
    var p = document.createElement("p"); 
    p.appendChild(document.createTextNode(str)); 
    return p.innerHTML; 
} 

или короткая альтернатива с использованием Option() конструктора

function escapeHTML(str){ 
    return new Option(str).innerHTML; 
} 
+1

это правильный ответ –

0

Вы можете закодировать все символы в строке:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})} 

Или просто цель главных героев беспокоиться о (&, inebreaks, <,>, "и '):

function encode(r){ 
 
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"}) 
 
} 
 

 
var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!'; 
 

 
test.value=encode(myString); 
 

 
testing.innerHTML=encode(myString); 
 

 
/************* 
 
* \x26 is &ampersand (it has to be first), 
 
* \x0A is newline, 
 
*************/
<p><b>What JavaScript Sees:</b></p> 
 

 
<textarea id=test rows="3" cols="55"></textarea> 
 

 
<p><b>What It Renders Too In HTML:</b></p> 
 

 
<div id="testing">www.WHAK.com</div>

Смежные вопросы