2009-07-13 12 views
45

Estoy buscando una expresión regular que coincida con cada carácter de línea nueva (\n) dentro de una etiqueta XML que es <content>, o dentro de cualquier etiqueta que sea dentro de esa etiqueta <content>, por ejemplo:Expresión regular para que coincida con cada carácter de línea nueva ( n) dentro de una etiqueta <content>

<blog> 
<text> 
(Do NOT match new lines here) 
</text> 
<content> 
(DO match new lines here) 
<p> 
(Do match new lines here) 
</p> 
</content> 
(Do NOT match new lines here) 
<content> 
(DO match new lines here) 
</content> 
+2

¿Tiene que ser una expresión regular? –

+0

¿También desea hacer coincidir solo las líneas nuevas o todo el texto según la respuesta de Quartz? –

+0

Sí, debería ser una expresión regular, y solo debería coincidir con líneas nuevas. –

Respuesta

66

en realidad ... no se puede utilizar una expresión regular simple aquí, al menos no uno. ¡Probablemente necesites preocuparte por los comentarios! Alguien puede escribir:

<!-- <content> blah </content> --> 

que puede tomar dos enfoques aquí:

  1. Strip todos los comentarios en primer lugar. Luego usa el enfoque de expresión regular.
  2. No use expresiones regulares y utilice un enfoque de análisis sensible al contexto que pueda realizar un seguimiento de si está anidado o no en un comentario.

Ten cuidado.

Tampoco estoy tan seguro de poder hacer coincidir todas las líneas nuevas a la vez. @Quartz sugirió éste:

<content>([^\n]*\n+)+</content> 

Esto coincidirá con cualquier etiqueta de contenido que tienen un carácter de nueva línea DERECHO ANTES de la etiqueta de cierre ... pero no estoy seguro de lo que quieres decir, haciendo coincidir todos los saltos de línea. ¿Desea poder acceder a todos los caracteres coincidentes de nueva línea? Si es así, la mejor opción es tomar todas las etiquetas de contenido y luego buscar todas las nuevas líneas que están anidadas. Algo de la misma familia:

<content>.*</content> 

pero hay una advertencia: expresiones regulares son codiciosos, por lo que esta expresión regular coincidirá con la primera etiqueta de apertura a cierre del último uno. En cambio, TIENES que suprimir la expresión regular para que no sea codicioso. En idiomas como Python, puedes hacer esto con el "?" símbolo de regex

Espero que con esto pueda ver algunas de las trampas y descubrir cómo desea proceder. Probablemente sea mejor utilizar una biblioteca de análisis XML, y luego iterar sobre todas las etiquetas de contenido.

Yo sé que no pueden ofrecer la mejor solución, pero al menos espero que vea la dificultad de esto y por qué otras respuestas pueden no ser correcta ...

ACTUALIZACIÓN 1:

Permítanme resumir un poco más y agregar algunos detalles más a mi respuesta. Voy a usar la sintaxis de expresiones regulares de Python porque es a lo que estoy más acostumbrado (perdónenme por adelantado ... es posible que necesiten escapar de algunos personajes ... comenten mi publicación y la corregiré):

Para quitar los comentarios, use esta expresión regular: Observe la "?" suprime el. * para que no sea codicioso.

De manera similar, para buscar etiquetas de contenido, use: . *?

También, usted puede ser capaz de probar esto, y acceder a cada carácter de nueva línea con el partido de objetos grupos():

<content>(.*?(\n))+.*?</content> 

Sé que mi escape está apagado, pero capta la idea. Este último ejemplo probablemente no funcionará, pero creo que es tu mejor opción para expresar lo que quieres. Mi sugerencia continúa: o agarra todas las etiquetas de contenido y hágalo usted mismo, o use una biblioteca de análisis.

ACTUALIZACIÓN 2:

Así que aquí está el código Python que debe trabajar. Todavía no estoy seguro de lo que quiere decir con "encontrar" todas las líneas nuevas. ¿Quieres las líneas enteras? O solo para contar cuántas líneas nuevas. Para obtener las líneas reales, tratan:

#!/usr/bin/python 

import re 

def FindContentNewlines(xml_text): 
    # May want to compile these regexes elsewhere, but I do it here for brevity 
    comments = re.compile(r"<!--.*?-->", re.DOTALL) 
    content = re.compile(r"<content>(.*?)</content>", re.DOTALL) 
    newlines = re.compile(r"^(.*?)$", re.MULTILINE|re.DOTALL) 

    # strip comments: this actually may not be reliable for "nested comments" 
    # How does xml handle <!-- <!-- --> -->. I am not sure. But that COULD 
    # be trouble. 
    xml_text = re.sub(comments, "", xml_text) 

    result = [] 
    all_contents = re.findall(content, xml_text) 
    for c in all_contents: 
     result.extend(re.findall(newlines, c)) 

    return result 

if __name__ == "__main__": 
    example = """ 

<!-- This stuff 
ought to be omitted 
<content> 
    omitted 
</content> 
--> 

This stuff is good 
<content> 
<p> 
    haha! 
</p> 
</content> 

This is not found 
""" 
    print FindContentNewlines(example) 

Este programa imprime el resultado:

['', '<p>', ' haha!', '</p>', ''] 

El primer y último cadenas vacías provienen de los caracteres de nueva línea inmediatamente anterior al primer <p> y el que viene justo después de el </p>. En general, esto (en su mayor parte) hace el truco. Experimenta con este código y refínalo para tus necesidades. Imprima las cosas en el medio para que pueda ver lo que las expresiones regulares coinciden y no coinciden.

Espero que esto ayude :-).

PD: No tuve mucha suerte probando mi expresión regular de mi primera actualización para capturar todas las nuevas líneas ... hágamelo saber si lo hace.

+0

Aquí están los documentos de expresiones regulares que analicé para python cuando escribí el código anterior (debería ser útil si no está familiarizado con las expresiones regulares en python): http://docs.python.org/library/re.html – Tom

+2

@Moayad: por cierto, este método seguramente no funcionará si hay etiquetas anidadas ... y NO regex podrá manejar eso. Regexes realmente NO son adecuados para este problema. – Tom

+0

Muchas gracias por esta explicación detallada :) Definitivamente me ayudará a decidir qué hacer con ese problema. ¡Gracias de nuevo! –

4
<content>(?:[^\n]*(\n+))+</content> 
+1

¿Qué tal hacer que los cuantificadores no sean codiciosos? ([^ \ n] *? \ N +?) +?

+0

@Codebender, su código coincide con todo dentro de la etiqueta < content>, quiero hacer coincidir solo las nuevas líneas. –

+0

Quarz, gracias, pero eso no es lo que estoy buscando, su RegEx compara cada carácter entre la primera etiqueta de apertura < content> y la última etiqueta de cierre < /content>. He actualizado el ejemplo para hacerlo un poco más claro. –

Cuestiones relacionadas