Estoy de acuerdo en que la herramienta correcta para analizar XML y especialmente HTML es un analizador y no un motor de expresión regular. Sin embargo, como otros han señalado, a veces usar una expresión regular es más rápido, más fácil y hace el trabajo si conoce el formato de datos.
Microsoft en realidad tiene una sección de Mejores prácticas para expresiones regulares en .NET Framework y habla específicamente sobre Considerar la fuente de entrada .
Las expresiones regulares tienen limitaciones, pero ¿ha considerado lo siguiente?
El marco .NET es único cuando se trata de expresiones regulares en el sentido de que admite definiciones de grupos de equilibrio .
Por esta razón, creo que PUEDES analizar XML usando expresiones regulares. Sin embargo, tenga en cuenta que debe ser XML válido (los navegadores son muy indulgentes con HTML y permiten una sintaxis XML incorrecta dentro de HTML ). Esto es posible ya que la "Definición de grupo de equilibrio" permitirá que el motor de expresión regular actúe como un PDA.
Cita del artículo 1 citado anteriormente:
Motor de expresión regular .NET
Como se describió anteriormente, las construcciones adecuadamente equilibradas no pueden describirse mediante una expresión regular. Sin embargo, el motor de expresión regular .NET proporciona algunas construcciones que permiten reconocer las construcciones equilibradas.
(?<group>)
- empuja el resultado capturado en la pila de captura con el nombre del grupo.
(?<-group>)
- saca la captura más superior con el grupo de nombres de la pila de captura.
(?(group)yes|no)
- coincide con la parte yes si existe un grupo con el grupo de nombres; de lo contrario, no coincide con ninguna parte.
Estas construcciones permiten que una expresión regular .NET emule un PDA restringido al permitir esencialmente versiones simples de las operaciones de pila: push, pop y empty. Las operaciones simples son más o menos equivalentes a incrementar, disminuir y comparar a cero respectivamente. Esto permite que el motor de expresiones regulares .NET reconozca un subconjunto de los lenguajes libres de contexto, en particular los que solo requieren un contador simple. Esto a su vez permite que las expresiones regulares .NET no tradicionales reconozcan construcciones individualmente equilibradas.
Considere la siguiente expresión regular:
(?=<ul\s+id="matchMe"\s+type="square"\s*>)
(?>
<!-- .*? --> |
<[^>]*/> |
(?<opentag><(?!/)[^>]*[^/]>) |
(?<-opentag></[^>]*[^/]>) |
[^<>]*
)*
(?(opentag)(?!))
Usa las banderas:
- Linea sola
- IgnorePatternWhitespace (no es necesario si contrae regex y elimina todos los espacios en blanco)
- IgnoreCase (no es necesario)
Expresión regular explicada (en línea)
(?=<ul\s+id="matchMe"\s+type="square"\s*>) # match start with <ul id="matchMe"...
(?> # atomic group / don't backtrack (faster)
<!-- .*? --> | # match xml / html comment
<[^>]*/> | # self closing tag
(?<opentag><(?!/)[^>]*[^/]>) | # push opening xml tag
(?<-opentag></[^>]*[^/]>) | # pop closing xml tag
[^<>]* # something between tags
)* # match as many xml tags as possible
(?(opentag)(?!)) # ensure no 'opentag' groups are on stack
Puede probar esto en A Better .NET Regular Expression Tester .
Usé la fuente de muestra de:
<html>
<body>
<div>
<br />
<ul id="matchMe" type="square">
<li>stuff...</li>
<li>more stuff</li>
<li>
<div>
<span>still more</span>
<ul>
<li>Another >ul<, oh my!</li>
<li>...</li>
</ul>
</div>
</li>
</ul>
</div>
</body>
</html>
Esto encontró el partido:
<ul id="matchMe" type="square">
<li>stuff...</li>
<li>more stuff</li>
<li>
<div>
<span>still more</span>
<ul>
<li>Another >ul<, oh my!</li>
<li>...</li>
</ul>
</div>
</li>
</ul>
aunque en realidad salió así:
<ul id="matchMe" type="square"> <li>stuff...</li> <li>more stuff</li> <li> <div> <span>still more</span> <ul> <li>Another >ul<, oh my!</li> <li>...</li> </ul> </div> </li> </ul>
Por último, realmente disfruté el artículo de Jeff Atwood: Parsing Html The Cthulhu Way . Curiosamente, cita la respuesta a esta pregunta que actualmente tiene más de 4k votos.