development

HTML 엔터티 디코딩

big-blog 2020. 4. 17. 08:15
반응형

HTML 엔터티 디코딩


이 질문에는 이미 답변이 있습니다.

JavaScript 또는 JQuery를 사용하여 HTML 엔터티를 어떻게 인코딩하고 디코딩합니까?

var varTitle = "Chris' corner";

나는 그것이되고 싶다 :

var varTitle = "Chris' corner";

당신은 다음과 같은 것을 시도 할 수 있습니다 :

var Title = $('<textarea />').html("Chris&apos; corner").text();
console.log(Title);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

JS 피들 .

보다 대화식 버전 :

$('form').submit(function() {
  var theString = $('#string').val();
  var varTitle = $('<textarea />').html(theString).text();
  $('#output').text(varTitle);
  return false;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post">
  <fieldset>
    <label for="string">Enter a html-encoded string to decode</label>
    <input type="text" name="string" id="string" />
  </fieldset>
  <fieldset>
    <input type="submit" value="decode" />
  </fieldset>
</form>

<div id="output"></div>

JS 피들 .


답변으로 승인 된 jQuery 코드를 사용하지 않는 것이 좋습니다. 페이지에 디코딩 할 문자열을 삽입하지는 않지만 스크립트 및 HTML 요소와 같은 항목을 작성합니다. 이것은 우리가 필요로하는 것보다 더 많은 코드입니다. 대신, 더 안전하고 최적화 된 기능을 사용하는 것이 좋습니다.

var decodeEntities = (function() {
  // this prevents any overhead from creating the object each time
  var element = document.createElement('div');

  function decodeHTMLEntities (str) {
    if(str && typeof str === 'string') {
      // strip script/html tags
      str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '');
      str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
      element.innerHTML = str;
      str = element.textContent;
      element.textContent = '';
    }

    return str;
  }

  return decodeHTMLEntities;
})();

http://jsfiddle.net/LYteC/4/

이 함수를 사용하려면 그냥 호출 decodeEntities("&amp;")하면 jQuery 버전과 동일한 기본 기술이 사용되지만 jQuery의 오버 헤드는없고 입력에서 HTML 태그를 삭제 한 후에 사용됩니다. HTML 태그를 필터링하는 방법은 허용 된 답변에 대한 Mike Samuel의 의견참조하십시오 .

이 함수는 프로젝트에 다음 줄을 추가하여 jQuery 플러그인으로 쉽게 사용할 수 있습니다.

jQuery.decodeEntities = decodeEntities;

Robert K가 말했듯이 사용자 입력은 DOM에 액세스 할 수 없으므로 jQuery.html (). text ()를 사용하여 HTML 엔티티를 해독하지 마십시오. 이것이 안전하지 않은 이유 에 대해서는 XSS대해 읽으십시오 .

대신 이스케이프스케이프 메소드 와 함께 제공되는 Underscore.js 유틸리티 벨트 라이브러리를 사용해보십시오 .

_. 탈출 (문자열)

HTML에 삽입, 대체 문자열 이스케이프 &, <, >, ", `, 및 '문자를.

_.escape('Curly, Larry & Moe');
=> "Curly, Larry &amp; Moe"

_.unescape (문자열)

탈출의 반대 대체 &amp;, &lt;, &gt;, &quot;, &#96;그리고 &#x27;자신의 이스케이프 대응과 함께.

_.unescape('Curly, Larry &amp; Moe');
=> "Curly, Larry & Moe"

더 많은 문자 디코딩을 지원하려면 밑줄 언 스케이프 방법을 복사하고 더 많은 문자를 맵에 추가하십시오.


다음은 div를 만들 필요가없고 "가장 일반적인"HTML 이스케이프 문자를 디코딩하는 빠른 방법입니다.

function decodeHTMLEntities(text) {
    var entities = [
        ['amp', '&'],
        ['apos', '\''],
        ['#x27', '\''],
        ['#x2F', '/'],
        ['#39', '\''],
        ['#47', '/'],
        ['lt', '<'],
        ['gt', '>'],
        ['nbsp', ' '],
        ['quot', '"']
    ];

    for (var i = 0, max = entities.length; i < max; ++i) 
        text = text.replace(new RegExp('&'+entities[i][0]+';', 'g'), entities[i][1]);

    return text;
}

Robert K의 솔루션에서 영감을 얻은이 버전은 HTML 태그를 제거하지 않으며 안전합니다.

var decode_entities = (function() {
    // Remove HTML Entities
    var element = document.createElement('div');

    function decode_HTML_entities (str) {

        if(str && typeof str === 'string') {

            // Escape HTML before decoding for HTML Entities
            str = escape(str).replace(/%26/g,'&').replace(/%23/g,'#').replace(/%3B/g,';');

            element.innerHTML = str;
            if(element.innerText){
                str = element.innerText;
                element.innerText = '';
            }else{
                // Firefox support
                str = element.textContent;
                element.textContent = '';
            }
        }
        return unescape(str);
    }
    return decode_HTML_entities;
})();

이것은 HTML 문자를 해독하는 가장 좋아하는 방법입니다. 이 코드를 사용하면 태그가 유지된다는 이점이 있습니다.

function decodeHtml(html) {
    var txt = document.createElement("textarea");
    txt.innerHTML = html;
    return txt.value;
}

예 : http://jsfiddle.net/k65s3/

입력:

Entity:&nbsp;Bad attempt at XSS:<script>alert('new\nline?')</script><br>

산출:

Entity: Bad attempt at XSS:<script>alert('new\nline?')</script><br>

다른 버전은 다음과 같습니다.

function convertHTMLEntity(text){
    const span = document.createElement('span');

    return text
    .replace(/&[#A-Za-z0-9]+;/gi, (entity,position,text)=> {
        span.innerHTML = entity;
        return span.innerText;
    });
}

console.log(convertHTMLEntity('Large &lt; &#163; 500'));


jQuery는 html 엔티티를 인코딩하고 디코딩하는 방법을 제공합니다.

"<div />"태그를 사용하면 모든 HTML이 제거됩니다.

function htmlDecode(value) {
    return $("<div/>").html(value).text();
}

function htmlEncode(value) {
    return $('<div/>').text(value).html();
}

"<textarea />"태그를 사용하면 html 태그가 유지됩니다.

function htmlDecode(value) {
    return $("<textarea/>").html(value).text();
}

function htmlEncode(value) {
    return $('<textarea/>').text(value).html();
}

"Robert K에서 영감을 얻은"또 다른 목록을 목록에 추가하려면 HTML 태그를 제거하지 않는 또 다른 안전한 버전이 있습니다. HTML 파서를 통해 전체 문자열을 실행하는 대신 엔티티 만 꺼내고 변환합니다.

var decodeEntities = (function() {
    // this prevents any overhead from creating the object each time
    var element = document.createElement('div');

    // regular expression matching HTML entities
    var entity = /&(?:#x[a-f0-9]+|#[0-9]+|[a-z0-9]+);?/ig;

    return function decodeHTMLEntities(str) {
        // find and replace all the html entities
        str = str.replace(entity, function(m) {
            element.innerHTML = m;
            return element.textContent;
        });

        // reset the value
        element.textContent = '';

        return str;
    }
})();

jQuery를 사용하여 HTML 엔터티를 디코딩하는 방법에 설명 된대로 신뢰할 수없는 HTML을 페이지에 삽입하는 것은 위험 합니까? .

한 가지 대안은 PHP의 html_entity_decode ( http://phpjs.org/functions/html_entity_decode:424 ) 의 JavaScript 전용 구현을 사용하는 것입니다 . 예제는 다음과 같습니다.

var varTitle = html_entity_decode("Chris&apos; corner");

Robert K의 솔루션에서 영감을 받아 html 태그를 제거 하고 다음과 같은 스크립트 및 이벤트 핸들러 실행을 방지합니다<img src=fake onerror="prompt(1)"> . 최신 Chrome, FF, IE에서 테스트되었습니다 (IE9에서는 작동하지만 테스트되지는 않음).

var decodeEntities = (function () {
        //create a new html document (doesn't execute script tags in child elements)
        var doc = document.implementation.createHTMLDocument("");
        var element = doc.createElement('div');

        function getText(str) {
            element.innerHTML = str;
            str = element.textContent;
            element.textContent = '';
            return str;
        }

        function decodeHTMLEntities(str) {
            if (str && typeof str === 'string') {
                var x = getText(str);
                while (str !== x) {
                    str = x;
                    x = getText(x);
                }
                return x;
            }
        }
        return decodeHTMLEntities;
    })();

간단히 전화하십시오 :

decodeEntities('<img src=fake onerror="prompt(1)">');
decodeEntities("<script>alert('aaa!')</script>");

정식 버전입니다

function htmldecode(s){
    window.HTML_ESC_MAP = {
    "nbsp":" ","iexcl":"¡","cent":"¢","pound":"£","curren":"¤","yen":"¥","brvbar":"¦","sect":"§","uml":"¨","copy":"©","ordf":"ª","laquo":"«","not":"¬","reg":"®","macr":"¯","deg":"°","plusmn":"±","sup2":"²","sup3":"³","acute":"´","micro":"µ","para":"¶","middot":"·","cedil":"¸","sup1":"¹","ordm":"º","raquo":"»","frac14":"¼","frac12":"½","frac34":"¾","iquest":"¿","Agrave":"À","Aacute":"Á","Acirc":"Â","Atilde":"Ã","Auml":"Ä","Aring":"Å","AElig":"Æ","Ccedil":"Ç","Egrave":"È","Eacute":"É","Ecirc":"Ê","Euml":"Ë","Igrave":"Ì","Iacute":"Í","Icirc":"Î","Iuml":"Ï","ETH":"Ð","Ntilde":"Ñ","Ograve":"Ò","Oacute":"Ó","Ocirc":"Ô","Otilde":"Õ","Ouml":"Ö","times":"×","Oslash":"Ø","Ugrave":"Ù","Uacute":"Ú","Ucirc":"Û","Uuml":"Ü","Yacute":"Ý","THORN":"Þ","szlig":"ß","agrave":"à","aacute":"á","acirc":"â","atilde":"ã","auml":"ä","aring":"å","aelig":"æ","ccedil":"ç","egrave":"è","eacute":"é","ecirc":"ê","euml":"ë","igrave":"ì","iacute":"í","icirc":"î","iuml":"ï","eth":"ð","ntilde":"ñ","ograve":"ò","oacute":"ó","ocirc":"ô","otilde":"õ","ouml":"ö","divide":"÷","oslash":"ø","ugrave":"ù","uacute":"ú","ucirc":"û","uuml":"ü","yacute":"ý","thorn":"þ","yuml":"ÿ","fnof":"ƒ","Alpha":"Α","Beta":"Β","Gamma":"Γ","Delta":"Δ","Epsilon":"Ε","Zeta":"Ζ","Eta":"Η","Theta":"Θ","Iota":"Ι","Kappa":"Κ","Lambda":"Λ","Mu":"Μ","Nu":"Ν","Xi":"Ξ","Omicron":"Ο","Pi":"Π","Rho":"Ρ","Sigma":"Σ","Tau":"Τ","Upsilon":"Υ","Phi":"Φ","Chi":"Χ","Psi":"Ψ","Omega":"Ω","alpha":"α","beta":"β","gamma":"γ","delta":"δ","epsilon":"ε","zeta":"ζ","eta":"η","theta":"θ","iota":"ι","kappa":"κ","lambda":"λ","mu":"μ","nu":"ν","xi":"ξ","omicron":"ο","pi":"π","rho":"ρ","sigmaf":"ς","sigma":"σ","tau":"τ","upsilon":"υ","phi":"φ","chi":"χ","psi":"ψ","omega":"ω","thetasym":"ϑ","upsih":"ϒ","piv":"ϖ","bull":"•","hellip":"…","prime":"′","Prime":"″","oline":"‾","frasl":"⁄","weierp":"℘","image":"ℑ","real":"ℜ","trade":"™","alefsym":"ℵ","larr":"←","uarr":"↑","rarr":"→","darr":"↓","harr":"↔","crarr":"↵","lArr":"⇐","uArr":"⇑","rArr":"⇒","dArr":"⇓","hArr":"⇔","forall":"∀","part":"∂","exist":"∃","empty":"∅","nabla":"∇","isin":"∈","notin":"∉","ni":"∋","prod":"∏","sum":"∑","minus":"−","lowast":"∗","radic":"√","prop":"∝","infin":"∞","ang":"∠","and":"∧","or":"∨","cap":"∩","cup":"∪","int":"∫","there4":"∴","sim":"∼","cong":"≅","asymp":"≈","ne":"≠","equiv":"≡","le":"≤","ge":"≥","sub":"⊂","sup":"⊃","nsub":"⊄","sube":"⊆","supe":"⊇","oplus":"⊕","otimes":"⊗","perp":"⊥","sdot":"⋅","lceil":"⌈","rceil":"⌉","lfloor":"⌊","rfloor":"⌋","lang":"〈","rang":"〉","loz":"◊","spades":"♠","clubs":"♣","hearts":"♥","diams":"♦","\"":"quot","amp":"&","lt":"<","gt":">","OElig":"Œ","oelig":"œ","Scaron":"Š","scaron":"š","Yuml":"Ÿ","circ":"ˆ","tilde":"˜","ndash":"–","mdash":"—","lsquo":"‘","rsquo":"’","sbquo":"‚","ldquo":"“","rdquo":"”","bdquo":"„","dagger":"†","Dagger":"‡","permil":"‰","lsaquo":"‹","rsaquo":"›","euro":"€"};
    if(!window.HTML_ESC_MAP_EXP)
        window.HTML_ESC_MAP_EXP = new RegExp("&("+Object.keys(HTML_ESC_MAP).join("|")+");","g");
    return s?s.replace(window.HTML_ESC_MAP_EXP,function(x){
        return HTML_ESC_MAP[x.substring(1,x.length-1)]||x;
    }):s;
}

용법

htmldecode("&sum;&nbsp;&gt;&euro;");

@William Lahti의 답변에 대한보다 기능적인 접근 방식 :

var entities = {
  'amp': '&',
  'apos': '\'',
  '#x27': '\'',
  '#x2F': '/',
  '#39': '\'',
  '#47': '/',
  'lt': '<',
  'gt': '>',
  'nbsp': ' ',
  'quot': '"'
}

function decodeHTMLEntities (text) {
  return text.replace(/&([^;]+);/gm, function (match, entity) {
    return entities[entity] || match
  })
}

게임에 약간 늦었다는 것을 알고 있지만 jQuery를 사용하여 HTML 엔터티를 디코딩하는 방법의 예로 다음 코드를 제공 할 수 있다고 생각했습니다.

var varTitleE = "Chris&apos; corner";
var varTitleD = $("<div/>").html(varTitleE).text();

console.log(varTitleE + " vs. " + varTitleD);​​​​​​​​​​​

콘솔 결과를 확인하기 위해 인스펙터 / 파이어 버그를 시작하는 것을 잊지 마십시오. 또는 간단하게 console.log (...) w / alert (...)

Chrome 관리자를 통한 내 콘솔의 내용은 다음과 같습니다.

Chris&apos; corner vs. Chris' corner

@Robert K와 @mattcasey는 모두 좋은 코드를 가지고 있기 때문에 앞으로 누군가가 사용할 수 있도록 CoffeeScript 버전으로 여기에 기여할 것이라고 생각했습니다.

    String::unescape = (strict = false) ->
      ###
      # Take escaped text, and return the unescaped version
      #
      # @param string str | String to be used
      # @param bool strict | Stict mode will remove all HTML
      #
      # Test it here:
      # https://jsfiddle.net/tigerhawkvok/t9pn1dn5/
      #
      # Code: https://gist.github.com/tigerhawkvok/285b8631ed6ebef4446d
      ###
      # Create a dummy element
      element = document.createElement("div")
      decodeHTMLEntities = (str) ->
        if str? and typeof str is "string"
          unless strict is true
            # escape HTML tags
            str = escape(str).replace(/%26/g,'&').replace(/%23/g,'#').replace(/%3B/g,';')
          else
            str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '')
            str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '')
          element.innerHTML = str
          if element.innerText
            # Do we support innerText?
            str = element.innerText
            element.innerText = ""
          else
            # Firefox
            str = element.textContent
            element.textContent = ""
        unescape(str)
      # Remove encoded or double-encoded tags
      fixHtmlEncodings = (string) ->
        string = string.replace(/\&amp;#/mg, '&#') # The rest, for double-encodings
        string = string.replace(/\&quot;/mg, '"')
        string = string.replace(/\&quote;/mg, '"')
        string = string.replace(/\&#95;/mg, '_')
        string = string.replace(/\&#39;/mg, "'")
        string = string.replace(/\&#34;/mg, '"')
        string = string.replace(/\&#62;/mg, '>')
        string = string.replace(/\&#60;/mg, '<')
        string
      # Run it
      tmp = fixHtmlEncodings(this)
      decodeHTMLEntities(tmp)

참조 https://jsfiddle.net/tigerhawkvok/t9pn1dn5/7/ 또는 https://gist.github.com/tigerhawkvok/285b8631ed6ebef4446d (JS를 컴파일 포함, 아마도이 답변에 비교하여 업데이트됩니다)


jquery 또는 모든 것을 미리 정의하지 않고 순수한 자바 스크립트로 수행하려면 인코딩 된 HTML 문자열을 필요한 모든 디코딩 단계에 대해 innerHTML 및 innerText (/ textContent) 속성을 통해 순환 할 수 있습니다.

<html>
  <head>
    <title>For every decode step, cycle through innerHTML and innerText </title>
    <script>
function decode(str) {
  var d = document.createElement("div");
  d.innerHTML = str; 
  return typeof d.innerText !== 'undefined' ? d.innerText : d.textContent;
}
    </script>
  </head>
  <body>
    <script>
var encodedString = "&lt;p&gt;name&lt;/p&gt;&lt;p&gt;&lt;span style=\"font-size:xx-small;\"&gt;ajde&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;da&lt;/em&gt;&lt;/p&gt;";
    </script>
    <input type=button onclick="document.body.innerHTML=decode(encodedString)"/>
  </body>
</html>

또한 인코딩 방법을 물었습니다. 서버 측 기능을 사용하거나 고유 한 객체를 만들어 매핑을 수행 할 수 있습니다 (예 : clj : 확장 문자를 변환하는 함수?


나는 그것이 선택한 솔루션의 정반대라고 생각합니다.

var decoded = $("<div/>").text(encodedStr).html();

시도 해봐 :)

참고 URL : https://stackoverflow.com/questions/5796718/html-entity-decode

반응형