ColdFusion: удаление атрибутов тега изображения из тега изображения - PullRequest
2 голосов
/ 02 декабря 2010

Я использую текстовый редактор YUI для форматирования текстовой области в создаваемой CMS. CMS позволяет пользователю загружать и включать изображения (это приложение для ведения блогов).

Непосредственно перед записью содержимого текстовой области в базу данных я бы хотел, чтобы ColdFusion обнаружил все теги изображений и удалил любые посторонние атрибуты, кроме SRC.

Например:

<IMG src="foo.jpg" title="Foo!" alt="Foo!" height="100" width="100" style="border=1;">

Должен выйти на другом конце как:

<IMG src="joo.jpg">

Задача:

  1. Атрибутами изображения могут быть любые, все или ни один из перечисленных в примере.
  2. Атрибуты изображения могут быть в любом порядке
  3. Тег изображения может быть расположен в любом месте текста текста из текстовой области

Это упражнение ColdFusion можно было бы избежать, если бы был способ сказать YUI, чтобы он не разрешал какие-либо атрибуты изображения, но я не уверен, что это (легко) возможно.

Большое спасибо заранее!

С уважением,

Kris

Ответы [ 2 ]

4 голосов
/ 02 декабря 2010

Самый стабильный и безопасный способ сделать это - загрузить HTML в DOM, убрать из него ненужные биты (или, что более безопасно, удалить все, кроме нужных бит) и преобразовать результат. вернуться к строке.

Однако - насколько мне известно, ColdFusion не предоставляет собственный анализатор DOM для HTML (только один для XML), а редактор форматированного текста YUI не создает XML (то есть XHTML). Это немного прискорбно, но не обязательно тупик.

  1. Для Java доступно множество HTML-анализаторов, и использовать объекты Java из ColdFusion легко. Вы можете включить один из них в свой проект.
  2. Вы можете преобразовать ввод HTML в XHTML (через jTidy), а затем использовать встроенный анализатор XML для реализации очистки. Вы можете даже преобразовать его обратно в HTML с помощью jTidy после того, как закончите.

Для начала я создал пример строгого белого списка для HTML-элементов и атрибутов во встроенном синтаксическом анализаторе XML:

<!--- to serve as an example of what you would get from jTidy --->
<cfset xhtml = XmlParse('
<html xmlns="http://www.w3.org/1999/xhtml">
  foo <img src="foo.jpg" title="Foo!" alt="Foo!" height="100" width="100" style="border=1;" />
  bar <a href="asdasdad" title="blah" target="baz" onmouseover="doSomethingEvil();">Link</a>
  baz <script type="text/javascript">doSomethingEvil();</script>
</html>', true)>

<!--- an easily configurable list of allowed elements and attributes --->
<cfset whiteList = StructNew()>
<cfset whiteList["html"] = "xmlns">
<cfset whiteList["head"] = "">
<cfset whiteList["body"] = "">
<cfset whiteList["img"]  = "src">
<cfset whiteList["a"]    = "href,title,name">

<!--- delete all attributes that are not white-listed --->
<cfloop collection="#whiteList#" item="tag">
  <cfset nodes = XmlSearch(xhtml, "//*[local-name() = '#tag#']")>
  <cfloop from="1" to="#ArrayLen(nodes)#" index="i">
    <cfset nodeAttrs = nodes[i].XmlAttributes>
    <cfloop list="#StructKeyList(nodeAttrs)#" index="attr">
      <cfif not ListFind(whiteList[tag], attr)>
        <cfset StructDelete(nodeAttrs, attr)>
      </cfif>
    </cfloop>
  </cfloop>
</cfloop>

<!--- delete all elements that are not white-listed --->
<cfset unwantedElements = XmlSearch(xhtml, "//*[not(contains(',#StructKeyList(whiteList)#,', concat(',',local-name(),',')))]")>
<cfloop from="1" to="#ArrayLen(unwantedElements)#" index="i">
  <cfset node = unwantedElements[i]>
  <cfset node.XmlAttributes["x-delete-flag"] = "true">

  <cfset parent = XmlSearch(node, "..")>
  <cfif ArrayLen(parent) eq 1 and StructKeyExists(parent[1], "XmlChildren")>
    <cfset childNodes = parent[1].XmlChildren>
    <cfloop from="#ArrayLen(childNodes)#" to="1" step="-1" index="k">
      <cfif StructKeyExists(childNodes[k].XmlAttributes, "x-delete-flag")>
        <cfset ArrayDeleteAt(childNodes, k)>
      </cfif>
    </cfloop>
  </cfif>
</cfloop>

Когда все готово, содержимое xhtml выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
  foo <img src="foo.jpg"/>
  bar <a href="asdasdad" title="blah">Link</a>
  baz 
</html>

Несколько объяснений:

  • Существует несколько описаний и UDF о том, как заставить Tidy работать в ColdFusion в Интернете, просто посмотрите на них.
  • Обработка XML DOM является громоздкой в ​​ColdFusion. Это не красиво и не элегантно, но все же лучше, чем пытаться использовать (не дай Бог) регулярные выражения для достижения того же эффекта. Я настоятельно не рекомендую вам использовать их для этой проблемы.
  • Используйте <cfdump>, чтобы почувствовать, как ColdFusion представляет XML-документы, и понять, что происходит в моем коде.
  • Второй бит (удаление всех элементов, не занесенных в белый список) немного волосатый. Очевидно, что невозможно более элегантно удалить узел из ColdFusion, поскольку XML-узлы ColdFusion не предоставляют ни методов parentNode(), ни removeChild() DOM. Эта реализация основана на подходе Бена Наделя к удалению узлов DOM в CF . Это работает, но я до боли осознаю, что это отстой. Простите за это. : - \
  • XPath: выражение "//*[not(contains(',#StructKeyList(whiteList)#,', concat(',',local-name(),',')))]" выбирает все узлы, локальное имя которых (т.е. не глядя на пространство имен XML) не содержится в списке разрешенных имен. В деталях:
    • // - сокращение от «где угодно в документе».
    • * означает «узел любого элемента».
    • Квадратные скобки обозначают условие. Дополнительные запятые должны гарантировать, что учитываются только полные совпадения - в противном случае contains() вернет "a" в качестве совпадения, например, в "abbr".
2 голосов
/ 02 декабря 2010

Я бы, наверное, сделал это в три этапа.Найдите все теги изображений, извлеките из них данные и замените оригиналы.

Сначала определите теги изображений.Я бы использовал для этого регулярное выражение - что-то вроде

<img [^>]+>

Это в основном говорит «запустите тег изображения, и возьмите все, кроме закрывающей скобки, затем закрывающей скобки. Используйте это в сочетании с reFind илиreFindNoCase для получения местоположения и длины каждого тега изображения.

Далее, поскольку вы хотите сохранить только href, вы можете найти его с помощью аналогичного метода. Захватите тег, используя функцию mid () и местоположение/ length сверху. Теперь, получите href с помощью регулярного выражения

href="[^"]+"

Теперь вы можете перебирать результаты, заменяя каждый тег изображения на тег изображения только с соответствующим href.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...