130

我有一个特定的字符串,我想检查它是否是 html。我正在使用正则表达式,但没有得到正确的结果。

我验证了我的正则表达式,它在这里工作正常。

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

这是小提琴,但正则表达式没有在那里运行。http://jsfiddle.net/wFWtc/

在我的机器上,代码运行良好,但结果是 false 而不是 true。这里缺少什么?

4

17 回答 17

383

用于检查字符串是否为 HTML 的更好的正则表达式是:

/^/

例如:

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

事实上,它非常好,它会true为传递给它的每个字符串返回,这是因为每个字符串都是 HTML。说真的,即使它的格式很差或无效,它仍然是 HTML。

如果您要查找的是 HTML 元素的存在,而不仅仅是任何文本内容,您可以使用以下内容:

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

它不会以任何方式帮助您解析 HTML,但它肯定会将字符串标记为包含 HTML 元素。

于 2013-03-17T08:43:31.380 回答
96

方法#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.from为 ES2015 方法,可替换为[].slice.call(doc.body.childNodes).
2. 调用中的箭头函数some可以替换为常用的匿名函数。

于 2013-03-17T08:40:41.890 回答
14

一点点验证:

/<(?=.*? .*?\/ ?>|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

于 2013-03-17T09:29:04.703 回答
13

zzzzBov上面的答案很好,但它不考虑杂散的结束标签,例如:

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

也捕获结束标签的版本可能是这样的:

/<[a-z/][\s\S]*>/i.test('foo </b> bar'); // true
于 2014-08-19T10:24:15.010 回答
12

这是我不时使用的一个草率的单线:

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

它基本上会返回true包含 a<后跟 的ANYTHING字符串>

ANYTHING我的意思基本上是除了一个空字符串之外的任何东西。

这不是很好,但它是单行的。

用法

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

如您所见,它远非完美,但在某些情况下可能会为您完成这项工作。

于 2016-04-21T14:50:32.613 回答
7

这里的所有答案都过于包容,他们只是寻找<后跟>. 没有完美的方法来检测字符串是否为 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'>")
于 2018-07-13T13:12:23.160 回答
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 ------------------------^

此外,您的 jsfiddle 不起作用,因为您onload在另一个onload处理程序中分配了一个处理程序 - 在左侧的 Frameworks & Extensions 面板中设置的默认设置是将 JS 包装在onload. 将其更改为 nowrap 选项并修复字符串文字转义并且它“有效”(在每个人都在评论中指出的约束范围内):http: //jsfiddle.net/wFWtc/4/

据我所知,JavaScript 正则表达式没有反向引用。所以你表达的这一部分:

</\1>

不会在 JS 中工作(但可以在其他一些语言中工作)。

于 2013-03-17T08:31:38.523 回答
3

使用 jQuery:

function isHTML(str) {
  return /^<.*?>$/.test(str) && !!$(str)[0];
}
于 2013-11-19T14:07:40.093 回答
3

/<\/?[^>]*>/.test(str)只检测是否包含html标签,可能是xml

于 2016-02-05T04:09:02.093 回答
3

在这种情况下使用 jQuery,最简单的形式是:

if ($(testString).length > 0)

如果$(testString).length = 1,这意味着里面有一个 HTML 标签textStging

于 2017-06-11T05:25:10.497 回答
2

虽然这是一个旧线程,但我只是想分享我为我的需要编写的解决方案:

function isHtml(input) {
    return /<[a-z]+\d?(\s+[\w-]+=("[^"]*"|'[^']*'))*\s*\/?>|&#?\w+;/i.test(input);
}

它应该涵盖我在这个线程中发现的大多数棘手的情况。在此页面上使用document.body.innerText和进行了测试document.body.innerHTML

我希望它对某人有用。:)

于 2021-06-03T12:53:12.543 回答
1

有一些奇特的解决方案涉及利用浏览器本身来尝试解析文本,识别是否构造了任何 DOM 节点,这将是……很慢。或者正则表达式会更快,但是……可能不准确。这个问题还引发了两个非常不同的问题:

Q1:字符串是否包含 HTML 片段?

字符串是否是 HTML 文档的一部分,包含 HTML 元素标记或编码实体?这可以用作字符串可能需要漂白/消毒或实体解码的指示:

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

在撰写本文时,您可以在所有现有答案的所有示例中看到这种模式,以及一些……相当可怕的 WYSIWYG 或 Word 生成的示例文本和各种字符实体引用。

Q2:字符串是 HTML 文档吗?

HTML 规范对于HTML 文档的定义非常松散。浏览器竭尽全力将几乎所有垃圾文本解析为 HTML。两种方法:要么只考虑所有 HTML(因为如果使用 Content-Type 交付,用户代理text/html将花费大量精力尝试将其解释为 HTML)或查找前缀标记:

<!DOCTYPE html>

就“格式良好”而言,几乎没有其他任何东西是“必需的”。以下是一个100% 完整、完全有效的 HTML 文档,其中包含您认为被省略的每个 HTML 元素:

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

是的。关于如何形成“缺失”元素,例如 、 和 ,有明确<html><head>规则<body>。虽然我觉得很有趣的是,SO 的语法突出显示在没有明确提示的情况下无法正确检测到这一点。

于 2020-02-05T14:25:23.057 回答
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);
于 2019-12-08T12:16:53.487 回答
0

由于最初的请求并不是说解决方案必须是正则表达式,只是尝试使用正则表达式。我会提供这个。如果可以解析单个子元素,它会说某些东西是 HTML。请注意,如果正文仅包含注释或 CDATA 或服务器指令,这将返回 false。

const isHTML = (text) => {
  try {
    const fragment = new DOMParser().parseFromString(text,"text/html");
    return fragment.body.children.length>0
  } catch(error) { ; }  
  return false;
}
于 2020-12-11T16:10:06.240 回答
0

这是我在自己的项目中使用的一种无正则表达式的方法。

如果您尝试在其他非 HTML 字符串中检测 HTML 字符串,您可以转换为 HTML 解析器对象,然后返回以查看字符串长度是否不同。IE:

Python 实现示例如下:

def isHTML(string):
    string1 = string[:]
    soup = BeautifulSoup(string, 'html.parser')  # Can use other HTML parser like etree
    string2 = soup.text

    if string1 != string2:
        return True
    elif string1 == string2:
        return False

它适用于我的 2800 个字符串样本。

伪代码将是

define function "IS_HTML"
  input = STRING
  set a copy of STRING as STRING_1
  parse STRING using an HTML parser and set as STRING_2
  IF STRING_1 is equal to STRING_2
  THEN RETURN TRUE
  ELSE IF STRING_1 is not equal to STRING_2
  THEN RETURN FALSE

这在我的测试用例中对我有用,它可能对你有用。

于 2021-01-28T19:45:37.727 回答
0

对于 xml 字符串,我需要类似的东西。我会把我想出的东西放在这里,以防它对任何人有用..

static isXMLstring(input: string): boolean {
    const reOpenFull = new RegExp(/^<[^<>\/]+>.*/);
    const reOpen = new RegExp(/^<[^<>\/]+>/);
    const reCloseFull = new RegExp(/(^<\/[^<>\/]+>.*)|(^<[^<>\/]+\/>.*)/);
    const reClose = new RegExp(/(^<\/[^<>\/]+>)|(^<[^<>\/]+\/>)/);
    const reContentFull = new RegExp(/^[^<>\/]+.*/);
    const reContent = new RegExp(/^[^<>&%]+/); // exclude reserved characters in content

    const tagStack: string[] = [];

    const getTag = (s: string, re: RegExp): string => {
      const res = (s.match(re) as string[])[0].replaceAll(/[\/<>]/g, "");
      return res.split(" ")[0];
    };

    const check = (s: string): boolean => {
      const leave = (s: string, re: RegExp): boolean => {
        const sTrimmed = s.replace(re, "");
        if (sTrimmed.length == 0) {
          return tagStack.length == 0;
        } else {
          return check(sTrimmed);
        }
      };

      if (reOpenFull.test(s)) {
        const openTag = getTag(s, reOpen);
        tagStack.push(openTag); // opening tag
        return leave(s, reOpen);
      } else if (reCloseFull.test(s)) {
        const openTag = tagStack.pop();
        const closeTag = getTag(s, reClose);
        if (openTag != closeTag) {
          return false;
        }
        // closing tag
        return leave(s, reClose);
      } else if (reContentFull.test(s)) {
        if (tagStack.length < 1) {
          return false;
        } else {
          return leave(s, reContent); // content
        }
      } else {
        return false;
      }
    };

    return check(input);
  }
于 2021-05-12T12:38:00.033 回答
-1

有一个 NPM 包 is-html 可以尝试解决这个问题https://github.com/sindresorhus/is-html

于 2020-05-13T03:16:52.457 回答