为什么这个函数不是 return 一个适用于 ListToArray 或 ValueList 的字符串?
Why does this function not return a string that will work ListToArray or ValueList?
我在 format.cfc
组件中创建了一个函数,其中 returns 一个没有任何 HTML 代码的字符串:
<cffunction name="RemoveHTML" access="public" returntype="string" output="false" hint="Returns a string without any html">
<cfargument name="UserString" required="yes">
<cfset var result = "#REReplaceNoCase(Canonicalize(ARGUMENTS.UserString,false,true),'<[^>]*(?:>|$)', '', 'ALL')#">
<cfreturn result>
</cffunction>
我现在想在每个 space 处拆分字符串并将其转换为列表。所以我尝试使用 ValueList() 和 ListToArray() 但它们不喜欢从函数返回的值。
使用 ValueList() 我收到一条错误消息:
Complex constructs are not supported with function ValueList
或者我在使用 ListToArray 时遇到此错误:
Complex object types cannot be converted to simple values
我基本上就是这样做的:
<!--- ValueList() --->
<title>#ValueList(Application.Format.RemoveHTML(UserString = rsProduct.Title), ' ')#</title>
<!--- ListToArray() --->
<title>#ListToArray(Application.Format.RemoveHTML(UserString = rsProduct.Title), ' ')#</title>
如果我删除 ListToArray() 或 ValueList() 函数,那么我会得到我期望的结果 - 一个没有 HTML 的产品标题字符串。
那么为什么函数不返回一个字符串,即使它看起来像一个字符串?还是我漏掉了一些显而易见的东西?
正如其他人在评论中指出的那样,ValueList
旨在 return 包含在查询对象的列中的值列表。它不适用于字符串值。
ListToArray
将列表转换为数组。然后你不能在你的 HTML 中输出一个数组。所以 ListToArray
工作正常,当您尝试在 cfoutput
中显示它时出现错误。
最好使用CF中的内置编码函数,例如encodeForHTML
。所以你可以这样做:
<title>#encodeForHTML(Application.Format.RemoveHTML(UserString = rsProduct.Title))#</title>
encodeForHTML
,可以接受一个可选的布尔值第二个参数(默认情况下为 false),以指示是否要规范化字符串。因此,您可能希望这样做而不是在自定义 RemoveHTML
函数中调用 Canonicalize
。毕竟你的函数被称为 RemoveHTML
而不是 RemoveHTMLAndCanonicalize
:)
更新
回应 OP 的评论。
要从 'space delimited' 字符串中获取逗号分隔列表,则可以使用 replace
函数。类似于:
<title>#encodeForHTML(replace(RemoveHTML(rsProduct.Title), " ", ",", "all"))#</title>
你当然可以把 replace
放在你的自定义函数中,我只是演示它是如何工作的。
你需要注意,它会用逗号替换所有空格,所以如果你连续有 2 个或更多空格,那么它会显示 ,,
(取决于有多少空格)。要解决这个问题,您可以使用如下正则表达式:
<title>#encodeForHTML(reReplace(RemoveHTML(rsProduct.Title), " +", ",", "all"))#</title>
您也可以使用 listChangeDelims
代替 reReplace
,因为它会忽略空元素。
<title>#encodeForHTML(listChangeDelims(RemoveHTML(rsProduct.Title), ",", " "))#</title>
就我个人而言,我会选择正则表达式版本,因为它更强大,您需要将它包装在一个函数中,但可以保持视图美观和干净。
我认为有多种方法可以做到这一点,考虑下面是我的文字
<cfset myText = "Samsung Galaxy Note 4"/>
第一种方法,使用简单的替换功能
<cfset firstSolution = replace(myText," ",",","all")/>
<cfdump var="#firstSolution#" />
第二种方法使用reReplace方法
<cfset secondSolution = rEReplace(myText,"\s+",",","all")/>
<cfdump var="#secondSolution#" />
如果我是你,我会使用第二种方法,因为如果我的字符串中有多个空格,那么我将得到单个 ',' 而不是得到多个 ',' 标题中使用了给定的字符串页面的标题不正确,我不会冒任何风险。
我在 format.cfc
组件中创建了一个函数,其中 returns 一个没有任何 HTML 代码的字符串:
<cffunction name="RemoveHTML" access="public" returntype="string" output="false" hint="Returns a string without any html">
<cfargument name="UserString" required="yes">
<cfset var result = "#REReplaceNoCase(Canonicalize(ARGUMENTS.UserString,false,true),'<[^>]*(?:>|$)', '', 'ALL')#">
<cfreturn result>
</cffunction>
我现在想在每个 space 处拆分字符串并将其转换为列表。所以我尝试使用 ValueList() 和 ListToArray() 但它们不喜欢从函数返回的值。
使用 ValueList() 我收到一条错误消息:
Complex constructs are not supported with function ValueList
或者我在使用 ListToArray 时遇到此错误:
Complex object types cannot be converted to simple values
我基本上就是这样做的:
<!--- ValueList() --->
<title>#ValueList(Application.Format.RemoveHTML(UserString = rsProduct.Title), ' ')#</title>
<!--- ListToArray() --->
<title>#ListToArray(Application.Format.RemoveHTML(UserString = rsProduct.Title), ' ')#</title>
如果我删除 ListToArray() 或 ValueList() 函数,那么我会得到我期望的结果 - 一个没有 HTML 的产品标题字符串。
那么为什么函数不返回一个字符串,即使它看起来像一个字符串?还是我漏掉了一些显而易见的东西?
正如其他人在评论中指出的那样,ValueList
旨在 return 包含在查询对象的列中的值列表。它不适用于字符串值。
ListToArray
将列表转换为数组。然后你不能在你的 HTML 中输出一个数组。所以 ListToArray
工作正常,当您尝试在 cfoutput
中显示它时出现错误。
最好使用CF中的内置编码函数,例如encodeForHTML
。所以你可以这样做:
<title>#encodeForHTML(Application.Format.RemoveHTML(UserString = rsProduct.Title))#</title>
encodeForHTML
,可以接受一个可选的布尔值第二个参数(默认情况下为 false),以指示是否要规范化字符串。因此,您可能希望这样做而不是在自定义 RemoveHTML
函数中调用 Canonicalize
。毕竟你的函数被称为 RemoveHTML
而不是 RemoveHTMLAndCanonicalize
:)
更新
回应 OP 的评论。
要从 'space delimited' 字符串中获取逗号分隔列表,则可以使用 replace
函数。类似于:
<title>#encodeForHTML(replace(RemoveHTML(rsProduct.Title), " ", ",", "all"))#</title>
你当然可以把 replace
放在你的自定义函数中,我只是演示它是如何工作的。
你需要注意,它会用逗号替换所有空格,所以如果你连续有 2 个或更多空格,那么它会显示 ,,
(取决于有多少空格)。要解决这个问题,您可以使用如下正则表达式:
<title>#encodeForHTML(reReplace(RemoveHTML(rsProduct.Title), " +", ",", "all"))#</title>
您也可以使用 listChangeDelims
代替 reReplace
,因为它会忽略空元素。
<title>#encodeForHTML(listChangeDelims(RemoveHTML(rsProduct.Title), ",", " "))#</title>
就我个人而言,我会选择正则表达式版本,因为它更强大,您需要将它包装在一个函数中,但可以保持视图美观和干净。
我认为有多种方法可以做到这一点,考虑下面是我的文字
<cfset myText = "Samsung Galaxy Note 4"/>
第一种方法,使用简单的替换功能
<cfset firstSolution = replace(myText," ",",","all")/>
<cfdump var="#firstSolution#" />
第二种方法使用reReplace方法
<cfset secondSolution = rEReplace(myText,"\s+",",","all")/>
<cfdump var="#secondSolution#" />
如果我是你,我会使用第二种方法,因为如果我的字符串中有多个空格,那么我将得到单个 ',' 而不是得到多个 ',' 标题中使用了给定的字符串页面的标题不正确,我不会冒任何风险。