2009-06-09 16 views
10

Estoy buscando una forma rápida de analizar las etiquetas HTML de una cadena ColdFusion. Estamos obteniendo un feed RSS que potencialmente podría contener algo. Entonces estamos manipulando la información y luego escupiéndola a otro lugar. Actualmente estamos haciendo esto con una expresión regular. ¿Hay una mejor manera de hacer esto?¿Cómo puedo eliminar etiquetas HTML de una cadena ColdFusion?

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

Estamos utilizando ColdFusion 8.

Respuesta

14

Negación Soy un firme defensor de la utilización de un analizador adecuado (en lugar de expresiones regulares) para analizar HTML. Sin embargo, esta pregunta no se trata de de análisis HTML, sino de que destruye. Para todas las tareas que van más allá de eso, use un analizador.


Creo que su expresión regular es buena. Siempre que no haya nada más que eliminando todas las etiquetas HTML de la entrada, usar una expresión regular como la suya es seguro.

Cualquier otra cosa sería probablemente más problemas de lo que vale, pero que podría escribir una pequeña función que recorra la cadena char-por-char de una vez y elimina todo lo que está dentro de los soportes de etiquetas — por ejemplo:

  • interruptor en un "Intag" bandera tan pronto como se encuentra con un carácter "<",
  • interruptor de apagado tan pronto como se encuentra con ">"
  • personajes copia a la cadena de salida, siempre y cuando el indicador está apagado
  • para el rendimiento, utilice un objeto StringBuilder de Java en lugar de la concatenación de cadenas

Para una parte de alta demanda de su aplicación, esto puede ser más rápido que la expresión regular. Pero la expresión regular es limpia y probablemente lo suficientemente rápida.

Tal vez esta expresión regular modificado tiene algunas ventajas para usted:

<[^>]*(?:>|$) 
  • capturas etiquetas sin cerrar al final de la cadena
  • [^>]* es mejor que (.|\n)

El uso de REReplaceNoCase() es innecesario cuando no hay letras reales en el patrón. La coincidencia de expresiones regulares insensible a mayúsculas y minúsculas es más lenta que hacerlo con mayúsculas y minúsculas.

+0

He encontrado <[^>] *> como una posible expresión regular modificada. ¿Qué ventaja ofrece la segunda mitad de los suyos? – Jason

+0

Como dije: Captura etiquetas no cerradas al final de la cadena. "(?:> | $)" se lee como "un corchete de etiqueta de cierre o el final de la cadena". El resto de la expresión regular es equivalente a la alternativa que has encontrado. "[^>] *" generalmente es más recomendable que "(. | \ n) *?", porque es más explícito y es más rápido. – Tomalak

+1

Recomiendo hacer una segunda pasada para reemplazar con >, porque es posible que tenga algunas sobras. – Kip

2

La mejor manera es generalmente forzar < a &lt; y > a &gt;. De esta forma, no está haciendo suposiciones sobre la naturaleza del mensaje. Alguien puede estar hablando de <tags> o tratando de ser <<expressive>> o describiendo una pulsación de tecla <Ctrl>+C o usando las matemáticas 1 <x> 3.Incluso emoticones podrían desencadenar la expresión regular <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> 
+1

@SpliFF: En cuanto a "Incluso los emoticones podrían desencadenar la expresión regular", no, no podrían. Se codificarían como "< 8P". – Tomalak

+0

Sí, él dice que sus datos provienen de una fuente RSS. si el feed es correcto, el único bare < and > sería de etiquetas, los demás serían <y>.Es muy posible que la fuente de alimentación pueda estar mal formada, pero ese sería el problema del proveedor (lo que probablemente arruinaría cualquier analizador de fuentes). – Kip

+0

¿Es ]]> no válido en una descripción de fuente RSS? –

7

HTML no es un lenguaje regular, por lo que el uso de expresiones regulares en HTML (no controlado) es algo que se debe hacer con mucho cuidado (si acaso).

Consideremos, por ejemplo, el válida segmento siguiente del HTML:

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

Se habrá dado cuenta cómo el resaltador de sintaxis está ahogando en que - al igual que la expresión regular existente que ha sido ofrecido.

A menos que usted puede estar seguro de que la cadena está procesando no contendrá código HTML similar a la anterior, se debe evitar hacer suposiciones/compromiso, que una sola/ruta pura expresión regular sería forzarlo a hacer.

. (Nota: El mismo problema se aplica al método sugerido char-por-char demasiado)


para resolver su problema, se debe utilizar un analizador DOM para analizar su cadena en un objeto HTML, de enlace a través de cada elemento y convirtiendo a texto.

Si tiene XHTML válido, entonces puede usar CF XmlParse() para producir el objeto que luego puede recorrer. Si podría ser HTML no XML, entonces no hay una opción incorporada con CF8, por lo que deberá investigar las opciones en Java/etc.

+0

ah, programación de barcos :) – jinglesthula

3

utilizo este:

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

99% de los casos funciona bien.

0
<cfset a = "<b><font color = 'red'>(PCB) <1 ppm </font></b>"> 

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

<cfdump var="#b#"> 

salida b = "(PCB) < 1 ppm"

la expresión regular "< [^> <] *>" eliminará todas las etiquetas y los caracteres dentro de esas etiquetas y no eliminar las etiquetas individuales como < o> que se puede utilizar como menor o mayor que el símbolo en la cadena

Cuestiones relacionadas