문자열이 html인지 확인


100

html인지 아닌지 확인하려는 특정 문자열이 있습니다. 정규식을 동일하게 사용하고 있지만 적절한 결과를 얻지 못했습니다.

내 정규식을 확인했고 여기에서 잘 작동합니다 .

var htmlRegex = new RegExp("<([A-Za-z][A-Za-z0-9]*)\b[^>]*>(.*?)</\1>");
return htmlRegex.test(testString);

여기에 바이올린이 있지만 정규식이 거기에서 실행되지 않습니다. http://jsfiddle.net/wFWtc/

내 컴퓨터에서는 코드가 정상적으로 실행되지만 결과로 true 대신 false가 표시됩니다. 여기에 무엇이 빠졌습니까?


5
HTML 구문 분석기를 사용하여 HTML을 구문 분석하십시오. 아직 읽지 않았다면 이것을 읽으십시오 .
프레데릭 Hamidi

3
오는 질문 킵은 aoutmatically 그 안에 HTML과 정규식으로 모든 질문에 댓글을 설정합니다 스택 봇이 있어야한다
Bartlomiej 레 완도 우 스키

3
그것은 당신이 수표에서 원하는 정교함의 수준에 달려 있습니다. 문자열에 적어도 하나 <와 적어도 하나가 포함되어 있는지 확인 >하고 HTML이라고 부르거나 올바른 HTML 구문 또는 그 사이의 모든 항목으로 엄격하게 유효한지 확인할 수 있습니다. 가장 간단한 경우에는 HTML 파서가 필요하지 않습니다.
JJJ

3
문자열이 HTML인지 확인하는 이유는 무엇입니까?
nhahtdh 2013 년

2
@ user1240679 : 유효한 마크 업 형식? 어떤 종류의 타당성? 가장 엄격한 의미에서이를 설명하려면 DTD가 필요합니다. 느슨한 의미에서 태그가 올바르게 일치하는지 확인하는 것이 좋습니다. 위의 두 경우 중 하나는 정규식에 적합하지 않습니다.
nhahtdh 2013 년

답변:


319

문자열이 HTML인지 확인하는 데 사용하는 더 나은 정규식은 다음과 같습니다.

/^/

예를 들면 :

/^/.test('') // true
/^/.test('foo bar baz') //true
/^/.test('<p>fizz buzz</p>') //true

사실, 그것은 모든 문자열이 HTML 이기 때문에 전달 된 모든 문자열에 true대해 반환 될 정도로 훌륭 합니다. 진지하게, 형식이 잘못되었거나 유효하지 않더라도 여전히 HTML입니다.

원하는 것이 단순히 텍스트 콘텐츠가 아닌 HTML 요소의 존재라면 다음과 같은 내용을 사용할 수 있습니다.

/<\/?[a-z][\s\S]*>/i.test()

어떤 식 으로든 HTML을 구문 분석하는 데 도움이되지는 않지만 확실히 문자열에 HTML 요소가 포함 된 것으로 플래그를 지정합니다.


52
나는 솔직히 내가 snark에 대해 더 많은 반대표를 얻지 못했다는 것에 놀랐습니다.
zzzzBov

8
@clenemt, a < b && a > cHTML 이라고 생각 하십니까?
zzzzBov

1
@zzzzBov 당신은 당신 a<b && a>c이 HTML 이라고 생각한다는 것을 알고 있습니다. 저는 HTML 탐지가 그렇게 단순화 될 수 있기를 바랍니다. 구문 분석은 결코 쉽지 않습니다.
oriadam

2
@oriadam, 컨텍스트는이 경우 요소를 감지하기위한 것입니다. 당신이 사용하는 경우 a < b && a > c브라우저가 켜집니다 ><에 문자를 &gt;하고 &lt;적절하게 기관. 대신에 a<b && a>c브라우저 를 사용 하면 a<b && a>c</b>공백이 없어 요소 <b가 열리기 때문에 마크 업이 해석됩니다 <b>. 여기에 제가 말하는 것에 대한 간단한 데모가 있습니다.
zzzzBov

4
이것은 아마도 내가 본 최고의 트롤 답변 일 것입니다. ;)
aandis

74

방법 # 1 . 다음은 문자열에 HTML 데이터가 포함되어 있는지 테스트하는 간단한 함수입니다.

function isHTML(str) {
  var a = document.createElement('div');
  a.innerHTML = str;

  for (var c = a.childNodes, i = c.length; i--; ) {
    if (c[i].nodeType == 1) return true; 
  }

  return false;
}

아이디어는 브라우저 DOM 파서가 제공된 문자열이 HTML처럼 보이는지 여부를 결정할 수 있도록하는 것입니다. 보시다시피 단순히 ELEMENT_NODE( nodeTypeof 1)을 확인합니다 .

몇 가지 테스트를했고 작동하는 것처럼 보입니다.

isHTML('<a>this is a string</a>') // true
isHTML('this is a string')        // false
isHTML('this is a <b>string</b>') // true

이 솔루션은 HTML 문자열을 올바르게 감지하지만 img / vide / etc와 같은 부작용이 있습니다. innerHTML에서 파싱되면 태그가 리소스 다운로드를 시작합니다.

방법 # 2 . 또 다른 방법은 DOMParser를 사용하며 로드 리소스 부작용이 없습니다.

function isHTML(str) {
  var doc = new DOMParser().parseFromString(str, "text/html");
  return Array.from(doc.body.childNodes).some(node => node.nodeType === 1);
}

참고 :
1. Array.fromES2015 방법이며 [].slice.call(doc.body.childNodes).
2. some호출중인 화살표 기능 을 일반적인 익명 기능으로 대체 할 수 있습니다.


3
이것은 대단한 아이디어입니다. 그러나이 함수는 닫는 태그 (예 :)를 감지 할 수 없습니다 isHTML("</a>") --> false.
Lewis

9
훌륭한 솔루션! .. 유일한 부정적인 측면 영향은 HTML에 이미지 src 속성과 같은 정적 리소스가 포함되어 있으면 innerHTML브라우저가 해당 리소스를 가져 오기 시작하게된다는 것입니다. :(
Jose Browne

DOM에 추가되지 않아도 @JoseBrowne?
kuus

1
@kuus 예, 추가하지 않아도 가능합니다. DOMParser 솔루션을 사용하십시오.
dfsq

1
좋은 생각이지만 허용되는 답변이 성능면에서 더 좋을까요? 특히 큰 문자열 (의도 된 말장난)이 있거나이 테스트를 많이 사용해야하는 경우.
DerpyNerd

13

다음을 통한 약간의 유효성 검사 :

/<(?=.*? .*?\/ ?>|br|hr|input|!--|wbr)[a-z]+.*?>|<([a-z]+).*?<\/\1>/i.test(htmlStringHere) 

이것은 빈 태그 (일부 사전 정의 됨) 및 /종료 된 XHTML 빈 태그를 검색하고 빈 태그 로 인해 HTML로 유효성을 검사합니다. 또는 태그 이름을 캡처하고 HTML로 유효성을 검사하기 위해 문자열에서 닫는 태그를 찾으려고 시도합니다.

데모 설명 : http://regex101.com/r/cX0eP2

최신 정보:

다음을 통한 완전한 검증 :

/<(br|basefont|hr|input|source|frame|param|area|meta|!--|col|link|option|base|img|wbr|!DOCTYPE).*?>|<(a|abbr|acronym|address|applet|article|aside|audio|b|bdi|bdo|big|blockquote|body|button|canvas|caption|center|cite|code|colgroup|command|datalist|dd|del|details|dfn|dialog|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frameset|head|header|hgroup|h1|h2|h3|h4|h5|h6|html|i|iframe|ins|kbd|keygen|label|legend|li|map|mark|menu|meter|nav|noframes|noscript|object|ol|optgroup|output|p|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video).*?<\/\2>/i.test(htmlStringHere) 

이것은 모든 HTML 태그를 포함하기 때문에 적절한 유효성 검사를 수행합니다. 먼저 빈 태그와 닫는 태그가 필요한 나머지 태그가 뒤 따릅니다.

데모 설명 : http://regex101.com/r/pE1mT5


1
하단 정규식은 작동하지만 " '<strong> hello world"와 같은 닫히지 않은 html 태그는 감지하지 못합니다. 이것은 깨진 html이므로 문자열로 취급해야하지만 실제적인 목적을 위해 앱이 이것들을 감지 할 수도 있습니다.
TK123

HTML은 사용자 에이전트를 염두에두고 설계되었습니다. "유효하지 않은"태그는 유효하지 않으며 알 수 없으며 허용됩니다. "잘못된"속성은 유효하지 않습니다. 이것은 특히 "웹 구성 요소"와 JSX와 같은 기술을 포함하기 시작할 때 특히 두드러집니다. 이는 일반적으로 섀도우 DOM을 생성하는 HTML과 더 풍부한 구성 요소 설명을 혼합합니다. 슬랩 파일 및 평가에 document.querySelector('strange')- 그것은 작동합니다.
amcgregor

(요약하면, 사양이 작성되는 방식으로 인해 HTML 마크 업을 "검증"하려는 시도는 본질적으로 바보의 심부름입니다. "잘못된"요소가있는 샘플 HTML 문서에 대한 링크는 100 % 완전한 형식입니다. 완전한 HTML 문서 ( 1997 년 이후의 또 다른 예)
amcgregor

10

위의 zzzzBov의 대답 은 좋지만 예를 들어 다음과 같이 길잃은 닫는 태그를 고려하지 않습니다.

/<[a-z][\s\S]*>/i.test('foo </b> bar'); // false

닫는 태그도 포착하는 버전은 다음과 같습니다.

/<[a-z/][\s\S]*>/i.test('foo </b> bar'); // true

댓글로 게시하는 대신 수정을 제안하는 것이 더 나을 수 있습니다.
Zlatin Zlatev

제 생각 <[a-z/][\s\S]*>에는-첫 번째 그룹의 슬래시에 주목하십시오.
Ryan Guill

7

내가 때때로 사용하는 엉성한 한 줄짜리가 있습니다.

var isHTML = RegExp.prototype.test.bind(/(<([^>]+)>)/i);

그것은 기본적으로 반환합니다 true포함하는 문자열에 대한 <다음 ANYTHING다음을 >.

으로는 ANYTHING, 나는 빈 문자열을 제외하고 기본적으로 아무 의미.

좋지는 않지만 한 줄짜리입니다.

용법

isHTML('Testing');               // false
isHTML('<p>Testing</p>');        // true
isHTML('<img src="hello.jpg">'); // true
isHTML('My < weird > string');   // true (caution!!!)
isHTML('<>');                    // false

보시다시피 완벽하지는 않지만 어떤 경우에는 당신을 위해 일할 수도 있습니다.


1
내가 필요한 것만. 화려하지 않고 깨끗합니다. 감사!
moeiscool jul.

6

여기에있는 모든 답변은 지나치게 포괄적이며 <뒤에 >. 문자열이 HTML인지 감지하는 완벽한 방법은 없지만 더 잘할 수 있습니다.

아래에서 종료 태그를 살펴보면 훨씬 더 엄격하고 정확 해집니다.

import re
re_is_html = re.compile(r"(?:</[^<]+>)|(?:<[^<]+/>)")

그리고 여기에 실제로 있습니다.

# Correctly identified as not HTML:
print re_is_html.search("Hello, World")
print re_is_html.search("This is less than <, this is greater than >.")
print re_is_html.search(" a < 3 && b > 3")
print re_is_html.search("<<Important Text>>")
print re_is_html.search("<a>")

# Correctly identified as HTML
print re_is_html.search("<a>Foo</a>")
print re_is_html.search("<input type='submit' value='Ok' />")
print re_is_html.search("<br/>")

# We don't handle, but could with more tweaking:
print re_is_html.search("<br>")
print re_is_html.search("Foo &amp; bar")
print re_is_html.search("<input type='submit' value='Ok'>")

4

문자열 리터럴에서 정규식을 만드는 경우 백 슬래시를 이스케이프해야합니다.

var htmlRegex = new RegExp("<([A-Za-z][A-Za-z0-9]*)\\b[^>]*>(.*?)</\\1>");
// extra backslash added here ---------------------^ and here -----^

정규식 리터럴을 사용하는 경우에는 필요하지 않지만 슬래시를 이스케이프해야합니다.

var htmlRegex = /<([A-Za-z][A-Za-z0-9]*)\b[^>]*>(.*?)<\/\1>/;
// forward slash escaped here ------------------------^

또한 onload다른 핸들러 내부 에 핸들러 를 할당했기 때문에 jsfiddle이 작동하지 않았습니다 onload. 왼쪽의 Frameworks & Extensions 패널에 설정된 기본값은 JS를 onload. 그것을 nowrap 옵션으로 변경하고 문자열 리터럴 이스케이프를 수정하면 "작동"합니다 (모든 사람이 주석에서 지적한 제약 내에서). http://jsfiddle.net/wFWtc/4/

내가 아는 한 JavaScript 정규식에는 역 참조가 없습니다. 이 부분은 다음과 같습니다.

</\1>

JS에서 작동하지 않습니다 (그러나 다른 언어에서는 작동합니다).



글쎄, 이것은 태그 중 하나가 괜찮아 보이는지 테스트하지만 나머지는 아무것도 아닙니다. OP가 원하는 "유효성"이 무엇인지 확실하지 않습니다.
nhahtdh 2013 년

1
대해 <br> <hr> <input...>@ user1240679?
CSᵠ 2013 년

3

/<\/?[^>]*>/.test(str) html 태그가 포함되어 있는지 여부 만 감지하고 xml 일 수 있습니다.


27 is < 42, and 96 > 42. 이것은 HTML이 아닙니다.
amcgregor

3

jQuery 사용 :

function isHTML(str) {
  return /^<.*?>$/.test(str) && !!$(str)[0];
}

2
isHTML("<foo>");// true를 반환합니다. isHTML("div");// div페이지에 s 가 있으면 true를 반환합니다 .
ACK_stoverflow

@yekta-당신은 무엇을 취하고 있습니까? 이것은 문자열이 html인지 아닌지 확인합니다. 내가 아는 한 이메일은 html 태그가 아닙니다 ... isHTML ('foo@bar.com ')-> false // 맞습니다
gtournie

1
문자열은 무엇이든 될 수 있습니다. HTML 태그를 알고 있다면 처음에 HTML인지 확인하는 이유는 무엇입니까? 는 @선택기에 대한 올바른 구문이 아닙니다. 따라서 jQuery 선택기에 전달하면 예외가 발생합니다 (예 : $("you@example.com")from !!$(str)[0]). 나는 구체적으로 그 !!$(str)[0] 부분을 언급하고있다 . 방금 답변을 편집했지만 이제 jQuery가 작업을 수행하기 전에 HTML을 확인하고 있습니다.
yekta

나는 저자가 그것이 단지 문자열인지 확인하고 싶지 않다고 생각합니다. 그게 요점입니다. 그가 원했던 것은 문자열이 HTML 뿐만 아니라 유효한 HTML 태그 인지 확인할 수있는 함수였습니다 (그렇지 않으면 이것은 약간 어리 석습니다). @ACK_stoverflow 주석을 읽은 후 내 대답을 업데이트했지만 간단한 정규식이해야한다고 확신합니다.
gtournie

3

이 경우 jQuery를 사용하면 가장 간단한 형식은 다음과 같습니다.

if ($(testString).length > 0)

만약 $(testString).length = 1, 이것은 내부에 하나의 HTML 태그가 있다는 것을 의미합니다 textStging.


바로 아래의 답변 ( "With jQuery"로 시작하여 4 년 전에 작성되었습니다!)에 따라 단일 진입 점에서 여러 용도를 잘못 선택했다고 생각해보십시오. $()CSS 선택기 작업입니다. 또한 텍스트 HTML 직렬화의 DOM 노드 팩토리입니다. 그러나 또한 ... jQuery에 대한 동일한 의존성으로 고통받는 다른 답변에 따르면 "div"는 HTML이 아니지만 페이지에 요소가 true있으면 반환 됩니다 <div>. jQuery를 불필요하게 포함하는 거의 모든 솔루션에서 기대할 수 있기 때문에 이것은 매우 나쁜 접근 방식입니다. (Let it die.)
amcgregor

2

브라우저 자체를 사용하여 텍스트 구문 분석을 시도하고 DOM 노드가 생성되었는지 식별하는 멋진 솔루션이 있습니다. 또는 더 빠르지 만… 잠재적으로 부정확 할 수있는 정규 표현식입니다. 이 문제에서 발생하는 두 가지 매우 뚜렷한 질문도 있습니다.

Q1 : 문자열에 HTML 조각이 포함되어 있습니까?

HTML 요소 마크 업 또는 인코딩 된 엔티티를 포함하는 HTML 문서 의 문자열 부분 입니까? 이것은 문자열에 표백 / 정리 또는 엔티티 디코딩이 필요할 수 있음을 나타내는 지표로 사용할 수 있습니다.

/</?[a-z][^>]*>|(\&(?:[\w\d]+|#\d+|#x[a-f\d]+);/

이 글을 쓰는 당시의 모든 기존 답변의 모든 예제와 일부 ... 다소 끔찍한 WYSIWYG 또는 Word 생성 샘플 텍스트 및 다양한 문자 엔티티 참조에 대해이 패턴이 사용되는 것을 볼 수 있습니다 .

Q2 : 문자열이 HTML 문서입니까?

HTML 사양은 놀랍게도가 HTML 문서를 고려 무엇으로 느슨한됩니다 . 브라우저는 거의 모든 가비지 텍스트를 HTML로 구문 분석하기 위해 극단적 인 길이로 이동합니다. 두 접근 (가 함께 제공되는 경우 이후 두 단지 모두의 HTML을 고려 text/htmlContent-Type을 큰 노력을 소비한다 시도 또는 접두어 마커의 모양 HTML 사용자 에이전트에 의해로 해석) :

<!DOCTYPE html>

"잘 형성됨"의 관점에서, 그 외에 "필수"는 거의 없습니다. 다음은 생략 된 것으로 생각되는 모든 HTML 요소를 포함 하는 100 % 완전하고 완전히 유효한 HTML 문서 입니다.

<!DOCTYPE html>
<title>Yes, really.</title>
<p>This is everything you need.

예. 이 같은 '실종'요소를 형성하는 방법에 대한 명시 적 규칙은 <html>, <head>하고 <body>. SO의 구문 강조 표시가 명시 적 힌트없이 제대로 감지하지 못한 것이 다소 재미 있습니다.


0

내 해결책은

const element = document.querySelector('.test_element');

const setHtml = elem =>{
    let getElemContent = elem.innerHTML;

    // Clean Up whitespace in the element
    // If you don't want to remove whitespace, then you can skip this line
    let newHtml = getElemContent.replace(/[\n\t ]+/g, " ");

    //RegEX to check HTML
    let checkHtml = /<([A-Za-z][A-Za-z0-9]*)\b[^>]*>(.*?)<\/\1>/.test(getElemContent);

    //Check it is html or not
    if (checkHtml){
        console.log('This is an HTML');
        console.log(newHtml.trim());
    }
    else{
        console.log('This is a TEXT');
        console.log(elem.innerText.trim());
    }
}

setHtml(element);

정규 표현식 더 포괄적 인 표현식에 비해 결함 이 많은 것으로 보이며 사전 처리 (초기 교체)를 요구하는 것은 매우 불행한 일입니다.
amcgregor

-1

이 문제를 해결할 수있는 NPM 패키지 is-html이 있습니다. https://github.com/sindresorhus/is-html


선언 된 doctype을 제외하고는 실패 하는 식을 사용하려고 시도하는 표현을 이해 하지 못하며 , 추가 종속성에서 가져온 알려진 HTML 요소로 구성된 "전체"패턴은 HTML이 작동하는 방식이 아니라는 사실을 무시합니다. 아주 아주 오래되었습니다. 또한 기본 패턴은 명시 적으로 <html><body>태그를 언급 하며 , 둘 다 전적으로 선택 사항 입니다. "XML과 일치하지 않음"테스트가 말하고 있습니다.
amcgregor

@amcgregor 솔루션이 더 낫다고 생각한다면 isHTML repo에 기여할 수 있습니까? regex101에서 테스트 모음을 추가 하시겠습니까? 지역 사회에 가치가있을 것입니다
Colin D

그 라이브러리의 근본적인 목적은 잘못된 것이며, 이해하지 못하는 태그의 존재로 인해 일반적으로 HTML이 아닌 것으로 거짓 플래그를 지정함으로써 많은 경우에 본질적으로 잘못 될 것입니다. 이렇게하면 유효성 검사 가 성공할 수 없습니다. 또한, 간단한 정규식 또는 (편집 : ) librar는 [이거] ... 우리가 어떻게 프로그램을 잊어 버린 수 , 및 노드 / NPM은 언어가 아니거나 내가 일반적으로 사용하고자하는 툴체인에 기여, 또는의 사용을 장려 .
amcgregor

좋아 amcgergor, 내가 돕고 자 할 때 당신은 나에게 꽤 부정적입니다. 나는 npm이 잘못 인도된다는 전제에 동의하지 않습니다. 스택 오버플로 답변이 미래에 약간의 조정으로 나왔다고 상상해보십시오. 나는 당신의 라이브러리를 사용하는 개발자로서 단지 업그레이드하고 더 적절한 행동을 얻을 것입니다. 대신, 나는 .... 깨진 행동으로 살아야 하거나이 스택 오버플로 답변을 다시 방문하여 편집을 받아야합니까? 그것이 대체 우주입니다
Colin D

부정? 나는 내 입장을 설명하고 다른 방법으로는 현명 해 보이는 일을하지 않는 이유를 설명했습니다. 그러나 내가 링크 한 기사 는 약간 더 자극적 인 첫 번째 (앞으로 링크 된) 후속 기사였으며 많은 논의를 불러 일으켰습니다. 그는 또한 거기에 링크 된 기술 논문을 맨 아래에 발표했습니다. 품질에 대한 증거로 재 작업에 대한 당신의 직감에 반대합니다. 참조 : §7.2 (및 왼쪽 패드 재해 및 eslint)
amcgregor
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.