检查字符串是否为html

时间:2013-03-17 08:23:53

标签: javascript regex

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

我验证了我的正则表达式并且工作正常here

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

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

在我的机器上,代码运行正常,但结果是错误而不是真。 这里缺少什么?

17 个答案:

答案 0 :(得分:252)

用于检查字符串是否为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元素。

答案 1 :(得分:60)

方法#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_NODEnodeType的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 /等的副作用。标签将在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)some调用中的箭头函数可以用通常的匿名函数替换。

答案 2 :(得分:12)

稍作验证:

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

答案 3 :(得分:7)

上面的

zzzzBov's answer很好,但它没有考虑到错误的结束标记,例如:

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

也可以捕获结束标记的版本:

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

答案 4 :(得分:6)

这是我不时使用的一个单调的单行:

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

正如你所看到的那样,它远非完美,但在某些情况下可能会为你完成工作。

答案 5 :(得分:4)

使用jQuery:

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

答案 6 :(得分:4)

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

答案 7 :(得分: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处理程序 - 默认情况下在框架和放大器中设置。左侧的扩展面板是将JS包装在onload中。将其更改为nowrap选项并修复字符串文字转义并使其“有效”(在所有人在评论中指出的约束内):http://jsfiddle.net/wFWtc/4/

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

</\1>

在JS中不起作用(但可以在其他语言中使用)。

答案 8 :(得分:4)

这里的所有答案都包含在内,它们只是在寻找<后跟>。没有完美的方法来检测字符串是否为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'>")

答案 9 :(得分:3)

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

if ($(testString).length > 0)

如果$(testString).length = 1,则表示textStging内有一个HTML标记。

答案 10 :(得分:2)

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

问题1:字符串是否包含HTML片段?

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

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

在撰写本文时,您可以从所有现有答案中看到this pattern in use的所有示例,还有一些……相当可笑的所见即所得或Word生成的示例文本以及各种字符实体引用。

问题2:字符串是HTML文档吗?

HTML specification is shockingly loose as to what it considers an HTML document。浏览器竭尽全力将几乎所有垃圾文本解析为HTML。两种方法:要么考虑所有HTML(因为如果提供了text/html Content-Type,则将花费大量的精力在 try 上,以由用户代理将其解释为HTML)或查看前缀标记:

<!DOCTYPE html>

就“格式良好”而言,“几乎没有其他要求”。以下是100% complete, fully valid HTML document,其中包含您认为已省略的每个HTML元素:

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

是的。关于如何形成“丢失”元素(例如<html><head><body>)有明确的规则。尽管我发现SO的语法高亮无法在没有显式提示的情况下正确地检测到它,这很可笑。

答案 11 :(得分:1)

我的解决方法是

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);

答案 12 :(得分:1)

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

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

它应该涵盖我在此线程中发现的大多数棘手案例。在此页面上使用 document.body.innerTextdocument.body.innerHTML 进行测试。

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

答案 13 :(得分:0)

由于最初的要求不是说解决方案必须是RegExp,因此只是尝试使用RegExp。我会提供这个。如果可以解析单个子元素,则表示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;
}

答案 14 :(得分:0)

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

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

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 个字符串样本。

答案 15 :(得分: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);
  }

答案 16 :(得分:-1)

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