Estoy trabajando en varios archivos HTML e intento hacer coincidir una etiqueta <p> dentro de un <li> dentro de un <ul>
Por ejemplo:
<ul> <li>1</li> <li><p>2</p></li> <li> <ul> <li><p>3</p></li> </ul> </li> </ul> Mi objetivo es hacer coincidir ambas etiquetas <p> (2 y 3) por separado con sus etiquetas principales <li> y <ul> más cercanas.
Aquí está el Regex que estoy usando
/<ul>.*?(<li.*?>).*?(<p.*?>.*?<\/p>)(.*?)(<\/li>)/gs
El problema ocurre cuando trato de hacer coincidir un html como este:
<ul> <li> <ul> <li></li> <p>4</p> </ul> </li> </ul> Coincide con la etiqueta <p> y las etiquetas padre <li> y <ul> más lejanas.
¿Alguien tiene una idea de cómo puedo arreglar esto?
Editar: suponiendo que necesito usar Regex para esta coincidencia. Podría terminar usando selectores en JS de todos modos como ustedes sugirieron, pero aún me gustaría saber si hay una solución fácil para este patrón ya que esta lógica ya existe en mi aplicación usando Regex.
¿Si su objetivo es corregir/encontrar código HTML incorrecto? Es decir, <p> como descendiente directo de <ul> no está permitido; por lo tanto, expresiones regulares, un mejor enfoque probablemente sería un analizador simple.
Que no; lo más simple sería algo como document.createElement + innerHTML + querySelectorAll .
Si usa RegExp, use negated <> como "delimitador" al hacer coincidir las etiquetas, es decir:
<foo[^>]*> // and [^<]*Aunque obviamente no es infalible. Rápido y sucio para su caso:
/<ul>[^<]*<li[^>]*>[^<]*<p[^>]*>([^<]*)/ | | | | | +-- ... | +-- not > +-- not < Se bloquearía con etiquetas dentro de <p> (es decir, depende del texto solo dentro de <p> ... </p> ).
Se le ha advertido que use expresiones regulares con HTML en los comentarios.
Son correctos, la estructura jerárquica significa que un patrón lineal no siempre puede encontrar la solución deseada.
Suponiendo que el HTML es válido de todos modos y solo hay espacios en blanco entre las etiquetas que está buscando, se me ocurrió esto:
\s*(<li.*>)?\s*(<p.*>.*<\/p>)\s*(<\/li>)?li circundante sea opcional, pero aún lo captura si existe (al menos en sus ejemplos).\s*.*? con .* : ¿No tienes que escribir .*? , * ya significa "0 o más" . Puedes experimentar con él aquí:
https://regex101.com/r/oyNweY/1
Esta es una respuesta parcial.
Lo mejor que pude hacer fue con /<ul>.*?(<li.*?>(?:(?!<li>).)*?<p.*?>.*?<\/p>(?:(?!<\/li>).)*<\/li>)/gs
Con
<ul> <li>1</li> <li><p>2</p></li> <li> <ul> <li><p>3</p></li> </ul> </li> </ul>da (el primero es obviamente incorrecto)
<li>1</li> <li><p>2</p></li> y <li><p>3</p></li>
Con
<ul> <li> <ul> <li></li> <p>4</p> </ul> </li> </ul>el resultado es
<li> <ul> <li></li> <p>4</p> </ul> </li>Quizás alguien pueda mejorarlo más