Почему эта функция не возвращает строку, которая будет работать ListToArray или ValueList?

Я создал функцию в компоненте format.cfc, которая возвращает строку без 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>

Теперь я хочу разбить строку в каждом пробеле и преобразовать ее в список. Поэтому я попытался использовать ValueList() и ListToArray(), но им не нравится значение, возвращаемое функцией.

Используя ValueList(), я получаю сообщение об ошибке:

Сложные конструкции не поддерживаются функцией ValueList.

Или я получаю эту ошибку при использовании ListToArray:

Сложные типы объектов не могут быть преобразованы в простые значения

Я в основном просто делаю это:

<!--- ValueList() --->
<title>#ValueList(Application.Format.RemoveHTML(UserString = rsProduct.Title), ' ')#</title>

<!--- ListToArray() --->
<title>#ListToArray(Application.Format.RemoveHTML(UserString = rsProduct.Title), ' ')#</title>

Если я удалю функцию ListToArray() или ValueList(), я верну то, что и ожидал — строку названия продукта без HTML.

Так почему же функция не возвращает строку, хотя она выглядит так? Или я упускаю что-то совершенно очевидное?


person volume one    schedule 14.12.2015    source источник
comment
Можете ли вы опубликовать вывод функции removeHtml и какой окончательный результат вы ожидаете?   -  person Keshav jha    schedule 14.12.2015
comment
ValueList() предназначен для работы с объектами запроса, поэтому его использование в простой строке неуместно. Для ListToArray() попробуйте использовать простую строку, которую вы вводите сами, например попробуйте это. Посмотрите, преобразуется ли он в массив.   -  person Dan Bracuk    schedule 14.12.2015
comment
Потому что valueList работает с запросом, а listToArray используется для преобразования списка в массив.   -  person Keshav jha    schedule 14.12.2015
comment
Если вы просто хотите заменить пробел на ',', вам нужно использовать replace() для этого   -  person Keshav jha    schedule 14.12.2015
comment
@DanBracuk Я не думаю, что пробелы возвращаются из строки как обычные пробелы. Если я выполняю EncodeForHTMLAttribute() для строки, я получаю такие вещи, как Samsung&#x20;Galaxy&#x20;Note&#x20;4   -  person volume one    schedule 14.12.2015
comment
Если вы хотите точно увидеть, что возвращает ваша функция, выведите это в текстовую область или в блок <pre>.   -  person Dan Bracuk    schedule 14.12.2015
comment
@DanBracuk Я вручную набрал и протестировал этот #ListToArray('Samsung Galaxy Note 4', ' ')#, и он отклоняет его как сложный тип объекта. Но это просто строка, которую я сам набрал вручную.   -  person volume one    schedule 14.12.2015
comment
@volumeone Вы используете <cfoutput>? Вы должны использовать <cfdump>, так как это сложный объект.   -  person Beginner    schedule 14.12.2015


Ответы (2)


Как отмечали другие в комментариях, ValueList предназначен для возврата списка значений, содержащихся в столбце объекта запроса. Это не будет работать со строковым значением.

ListToArray преобразует список в массив. Затем вы не можете вывести массив в свой HTML. Итак, ListToArray работает нормально, ошибка возникает, когда вы пытаетесь отобразить его в cfoutput.

Рекомендуется использовать встроенные функции кодирования в CF, например encodeForHTML. Итак, вы можете сделать что-то вроде:

<title>#encodeForHTML(Application.Format.RemoveHTML(UserString = rsProduct.Title))#</title>

encodeForHTML, может принимать необязательный логический второй аргумент (который по умолчанию равен false), чтобы указать, хотите ли вы канонизировать строку. Поэтому вы можете сделать это вместо вызова Canonicalize в вашей пользовательской функции RemoveHTML. Ведь ваша функция называется RemoveHTML, а не RemoveHTMLAndCanonicalize :)

Обновить

В ответ на комментарий ОП.

Чтобы получить список с разделителями-запятыми из вашей строки с разделителями-пробелами, вы можете использовать функцию 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>

Лично я бы выбрал версию с регулярным выражением, так как она более мощная, вы захотите обернуть ее в функцию, чтобы сохранить красивый и чистый вид.

person John Whish    schedule 14.12.2015
comment
Я могу это сделать, но мне нужно заменить пробелы запятой, чтобы составить список - person volume one; 14.12.2015
comment
Ах, хорошо, тогда просто используйте. заменить, чтобы заменить пробелы. Обновлю ответ. - person John Whish; 14.12.2015
comment
В том то и проблема, что не работает. Я вручную набрал и протестировал этот #ListToArray('Samsung Galaxy Note 4', ' ')#, и он отклонил его как сложный тип объекта. Но это просто строка, которую я сам набрал вручную. - person volume one; 14.12.2015
comment
Обновили ответ - надеюсь, что он решит вашу проблему и объяснит, что происходит. - person John Whish; 14.12.2015
comment
Если вы сделаете <cfdump var="#ListToArray('Samsung Galaxy Note 4', ' ')#">, вы поймете, почему он не может просто вывести, что внутри cfoutput это массив, а не строка. - person John Whish; 14.12.2015
comment
Riiiight Я получил это сейчас. И это решение в значительной степени отлично работает :) Спасибо, Джон. - person volume one; 14.12.2015

Я думаю, что есть несколько способов сделать это, рассмотрим ниже мой текст

<cfset myText = "Samsung Galaxy Note 4"/>

первый метод с использованием простой функции замены

<cfset firstSolution = replace(myText," ",",","all")/>
<cfdump var="#firstSolution#" />

Второй метод с использованием метода reReplace

<cfset secondSolution = rEReplace(myText,"\s+",",","all")/>
<cfdump var="#secondSolution#" />

Если бы я был вами, я бы использовал второй метод, потому что если у меня есть несколько пробелов в моей строке, то вместо получения нескольких «,» я получу один «,» заданная строка используется в заголовке страницы, я не стал бы рисковать иметь неправильное название.

person Keshav jha    schedule 14.12.2015
comment
Что делать, если в тексте есть запятые? - person Dan Bracuk; 14.12.2015
comment
Это тоже хорошо. Лично я использую [[:space:]] вместо \s+. - person volume one; 15.12.2015