在ColdFusion中解码数字HTML实体?

在ColdFusion中解码数字HTML实体?,coldfusion,html-entities,Coldfusion,Html Entities,我需要一种方法将数字HTML实体转换为它们的等价纯文本字符。例如,我想将实体转换为: é 进入角色: é 通过谷歌搜索,我发现了一个名为的函数,但这个函数只转换命名实体。有没有办法在ColdFusion中解码数字实体?自己编写一个应该很容易。只需编辑找到的HtmlUNEditFormat()函数,将它们包含在扁豆和扁豆字符的末尾。更新的答案: 感谢Todd Sharp指出了一种非常简单的方法,即使用Apache Commons StringEscapeUtils库,该库由

我需要一种方法将数字HTML实体转换为它们的等价纯文本字符。例如,我想将实体转换为:

é
进入角色:

é

通过谷歌搜索,我发现了一个名为的函数,但这个函数只转换命名实体。有没有办法在ColdFusion中解码数字实体?

自己编写一个应该很容易。只需编辑找到的HtmlUNEditFormat()函数,将它们包含在扁豆和扁豆字符的末尾。

更新的答案: 感谢Todd Sharp指出了一种非常简单的方法,即使用Apache Commons StringEscapeUtils库,该库由CF(和Railo)打包,因此您只需执行以下操作:

<cfset Entity = "&##0233;" />
<cfset StrEscUtils = createObject("java", "org.apache.commons.lang.StringEscapeUtils") />
<cfset Character = StrEscUtils.unescapeHTML(Entity) />
这一条适用于Railo,但我不记得CF是否支持该语法,因此您可能需要将其更改为:

<cffunction name="decodeHtmlEntity" returntype="String" output="false">
    <cfargument name="Entity" type="String" hint="&##<number>; or &<name>;" />
    <cfset var XmlDoc = XmlParse('<xml>#Arguments.Entity#</xml>') />
    <cfreturn XmlDoc.XmlRoot.XmlText />
</cffunction>

我在使用一种方法时发现了这个问题,根据黑盒原理,这种方法不能相信传入字符串是HTML实体编码的还是非HTML实体编码的

我已经修改了Peter Boughton的函数,这样它就可以安全地用于尚未使用HTML实体处理的字符串。(这似乎唯一重要的时候是目标字符串中出现松散的符号,即“Cats&Dogs”)。这个修改过的版本在出现任何不可预见的XML解析错误时也会稍微失败

<cffunction name="decodeHtmlEntity" returntype="string" output="false">
    <cfargument name="str" type="string" hint="&##<number>; or &<name>;" />
    <cfset var XML = '<xml>#arguments.str#</xml>' />
    <cfset var XMLDoc = '' />

    <!--- ampersands that aren't pre-encoded as entities cause errors --->
    <cfset XML = REReplace(XML, '&(?!(\##\d{1,3}|\w+);)', '&amp;', 'all') />

    <cftry>
        <cfset XMLDoc = XmlParse(XML) />
        <cfreturn XMLDoc.XMLRoot.XMLText />
        <cfcatch>
            <cfreturn arguments.str />
        </cfcatch>
    </cftry>
</cffunction>

这将安全地支持以下用例:

<cffunction name="notifySomeoneWhoCares" access="private" returntype="void">
    <cfargument name="str" type="string" required="true"
        hint="String of unknown preprocessing" />
    <cfmail from="process@domain.com" to="someoneWhoCares@domain.com"
        subject="Comments from Web User" format="html">
        Some Web User Spoke Thus:<br />
        <cfoutput>#HTMLEditFormat(decodeHTMLEntity(arguments.str))#</cfoutput>
    </cfmail>
</cffunction>

一些网络用户这样说:
#HTMLEditFormat(decodeHTMLEntity(arguments.str))#
该功能现在非常有用,可以确保web提交的内容在通过电子邮件发送或提交到数据库表之前是实体安全的(想想XSS)


希望这有帮助。

这里有另一个函数,可以解码字符串中的所有数字html字符实体。它不依赖于xml解析,因此可以处理包含不平衡xml标记的字符串。如果字符串中有大量实体,则效率不高,但如果没有/很少实体,则效率相当高。我只在Railo上测试过,而不是AdobeCF

<cffunction name="decodeHtmlEntities" returntype="String" output="false">
    <cfargument name="s" type="String"/>
    <cfset var LOCAL = {f = ReFind("&##([0-9]+);", ARGUMENTS.s, 1, true), map={}}>
    <cfloop condition="LOCAL.f.pos[1] GT 0">
        <cfset LOCAL.map[mid(ARGUMENTS.s, LOCAL.f.pos[1], LOCAL.f.len[1])] = chr(mid(ARGUMENTS.s, LOCAL.f.pos[2], LOCAL.f.len[2]))>
        <cfset LOCAL.f = ReFind("&##([0-9]+);", ARGUMENTS.s, LOCAL.f.pos[1]+LOCAL.f.len[1], true)>
    </cfloop>
    <cfloop collection=#LOCAL.map# item="LOCAL.key">
        <cfset ARGUMENTS.s = Replace(ARGUMENTS.s, LOCAL.key, LOCAL.map[LOCAL.key], "all")>
    </cfloop>
    <cfreturn ARGUMENTS.s />
</cffunction>


我认为大约有超过100000个潜在的数字实体。我当然可以添加几百个,涵盖最常用的实体,但我希望能涵盖所有的东西。如果你沿着这条路线走(不要;看我的答案),在确定它是否是十进制实体后,你可以做类似于
Chr(rereplace(Arguments.Entity,'\D','')
。十六进制实体将类似,但需要将十六进制转换为十进制才能使用Chr函数。(哦,在上述重新替换调用的末尾应该有一个“all”参数)实际上,如果这种方法比XML解析每个函数调用的单个字符快得多,我不会感到惊讶+1.对于一个更轻量级的选项,理论上我们应该能够深入到用于实现XmlParse的Java类中,并找到要使用的特定实体解码/解析方法-但我刚刚浏览了apidocs,没有找到任何内容。这非常好,非常感谢!为了好玩,我一直在深入研究一个Java解决方案,发现Apache commons字符串转义实用程序包含一个unescapeHtml函数。这里的文档:这可能会以更少的开销做同样的事情,但是它需要在服务器上安装一个新的Java类,重新启动等等。所以我还没有尝试过。就目前而言,这是完美的。再次感谢!实际上,CF随Apache commons一起提供,因此您可以简单地执行以下操作:#utils.unescapethtml(htmlEncodedString)#Todd,您应该将其作为一个独立的答案添加进来。您可能会发现这也很有用:chr(#i#)=#value#
<cffunction name="decodeHtmlEntities" returntype="String" output="false">
    <cfargument name="s" type="String"/>
    <cfset var LOCAL = {f = ReFind("&##([0-9]+);", ARGUMENTS.s, 1, true), map={}}>
    <cfloop condition="LOCAL.f.pos[1] GT 0">
        <cfset LOCAL.map[mid(ARGUMENTS.s, LOCAL.f.pos[1], LOCAL.f.len[1])] = chr(mid(ARGUMENTS.s, LOCAL.f.pos[2], LOCAL.f.len[2]))>
        <cfset LOCAL.f = ReFind("&##([0-9]+);", ARGUMENTS.s, LOCAL.f.pos[1]+LOCAL.f.len[1], true)>
    </cfloop>
    <cfloop collection=#LOCAL.map# item="LOCAL.key">
        <cfset ARGUMENTS.s = Replace(ARGUMENTS.s, LOCAL.key, LOCAL.map[LOCAL.key], "all")>
    </cfloop>
    <cfreturn ARGUMENTS.s />
</cffunction>