12

我正在寻找一种从 ColdFusion 字符串中解析 HTML 标签的快速方法。我们正在提取一个 RSS 提要,其中可能包含任何内容。然后我们对信息进行一些操作,然后将其吐回另一个地方。目前我们正在使用正则表达式来执行此操作。有一个更好的方法吗?

<cfloop from="1" to="#ArrayLen(myFeed.item)#" index="i">
  <cfset myFeed.item[i].description.value = 
   REReplaceNoCase(myFeed.item[i].description.value, '<(.|\n)*?>', '', 'ALL')>
</cfloop>

我们正在使用 ColdFusion 8。

4

6 回答 6

15

免责声明我强烈主张使用适当的解析器(而不是正则表达式)来解析 HTML。但是,这个问题不是关于解析HTML,而是关于破坏它。对于超出此范围的所有任务,请使用解析器。


我认为你的正则表达式很好。只要从输入中删除所有 HTML 标记,使用像您这样的正则表达式是安全的。

其他任何事情都可能比它的价值更麻烦,但是您可以编写一个小函数,逐个字符地遍历字符串并删除标记括号内的所有内容 - 例如:

  • <一遇到“ ”字符就打开“inTag”标志,
  • >一遇到“ ”就关掉
  • 只要标志关闭,就将字符复制到输出字符串
  • 为了提高性能,请使用 StringBuilder Java 对象而不是字符串连接

对于应用程序的高需求部分,这可能比正则表达式更快。但正则表达式很干净,可能足够快。

也许这个修改过的正则表达式对你有一些好处:

<[^>]*(?:>|$)
  • 在字符串末尾捕获未闭合的标签
  • [^>]*好于(.|\n)

REReplaceNoCase()当模式中没有实际字母时,不需要使用。不区分大小写的正则表达式匹配比区分大小写要慢。

于 2009-06-09T15:43:38.640 回答
7

HTML 不是正则语言,因此在(不受控制的)HTML 上使用正则表达式应该非常小心(如果有的话)。

例如,考虑以下有效的 HTML 片段:

<img src="boat.jpg" alt="a boat" title="My boat is > everything! I <3 my boat!">

你会注意到语法高亮是如何令人窒息的——就像已经提供的现有正则表达式一样。

除非您可以确定您正在处理的字符串不会包含与上述类似的 HTML 代码,否则您应该避免做出假设/妥协,单一/纯正则表达式路由会迫使您这样做。

(注意:同样的问题也适用于建议的 char-by-char 方法。)


要解决您的问题,您应该使用 DOM 解析器将您的字符串解析为 HTML 对象,循环遍历每个元素并转换为文本。

如果您有有效的 XHTML,那么您可以使用 CFXmlParse()来生成可以循环的对象。如果它可能是非 XML HTML,那么 CF8 没有内置选项,因此您必须研究 Java/etc 中的选项。

于 2009-06-09T19:09:18.913 回答
5

我用这个:

REReplaceNoCase(text, "<[^[:space:]][^>]*>", "", "ALL");

99% 的情况下它都能正常工作。

于 2013-12-30T11:26:10.593 回答
2

最好的方法通常是强制<to&lt;>to &gt;。这样,您就不会对消息的性质做出假设。有人可能正在谈论<tags>或试图成为<<expressive>>或描述击键<Ctrl>+C或使用数学1 < x > 3。即使是表情符号也可能触发正则表达式<8P X>

<cfloop from="1" to="#ArrayLen(myFeed.item)#" index="i">
    <cfset myFeed.item[i].description.value = ReplaceList(myFeed.item[i].description.value, '<,>', '&lt;,&gt;')>
</cfloop>
于 2009-06-09T15:46:10.637 回答
2

cflib是你的朋友:stripHTML

于 2009-06-10T17:29:11.200 回答
0
<cfset a = "<b><font color = 'red'>(PCB) <1 ppm </font></b>">

<cfset b = REReplaceNoCase(a, "<[^><]*>", '', 'ALL')>

<cfdump var="#b#">

输出 b = "(PCB) <1 ppm"

正则表达式 "<[^><]*>" 将删除所有标签和这些标签内的字符,并且不会删除像 < 或 > 这样可以用作小于或大于字符串中的符号的单个标签

于 2015-12-03T07:50:38.343 回答