Concordo que a ferramenta certa para analisar XML e especialmente HTML é um analisador e não um mecanismo de expressão regular. No entanto, como outros já apontaram, algumas vezes o uso de um regex é mais rápido, fácil e o trabalho é feito se você souber o formato dos dados.
A Microsoft, na verdade, possui uma seção de Práticas recomendadas para expressões regulares no .NET Framework e fala especificamente sobre Considerar a fonte de entrada .
Expressões regulares têm limitações, mas você considerou o seguinte?
A estrutura .NET é única quando se trata de expressões regulares, pois oferece suporte a definições de grupo de balanceamento .
Por esse motivo, acredito que você PODE analisar o XML usando expressões regulares. Observe, no entanto, que ele deve ser XML válido (os navegadores perdoam muito o HTML e permitem uma sintaxe XML ruim dentro do HTML ). Isso é possível, pois a "Definição do grupo de balanceamento" permitirá que o mecanismo de expressão regular atue como um PDA.
Citação do artigo 1 citado acima:
Mecanismo de expressão regular do .NET
Conforme descrito acima, construções adequadamente balanceadas não podem ser descritas por uma expressão regular. No entanto, o mecanismo de expressão regular do .NET fornece algumas construções que permitem que construções equilibradas sejam reconhecidas.
(?<group>)
- envia o resultado capturado na pilha de captura com o grupo de nomes.
(?<-group>)
- exibe a captura mais superior com o grupo de nomes fora da pilha de captura.
(?(group)yes|no)
- corresponde à parte yes, se existir um grupo com o nome group, caso contrário não corresponde a nenhuma parte.
Essas construções permitem que uma expressão regular do .NET emule um PDA restrito, permitindo essencialmente versões simples das operações da pilha: push, pop e empty. As operações simples são praticamente equivalentes a incrementar, decrementar e comparar a zero, respectivamente. Isso permite que o mecanismo de expressão regular do .NET reconheça um subconjunto das linguagens sem contexto, em particular as que exigem apenas um contador simples. Isso, por sua vez, permite que expressões regulares do .NET não tradicionais reconheçam construções individuais adequadamente balanceadas.
Considere a seguinte expressão regular:
(?=<ul\s+id="matchMe"\s+type="square"\s*>)
(?>
<!-- .*? --> |
<[^>]*/> |
(?<opentag><(?!/)[^>]*[^/]>) |
(?<-opentag></[^>]*[^/]>) |
[^<>]*
)*
(?(opentag)(?!))
Use as bandeiras:
- Única linha
- IgnorePatternWhitespace (não é necessário se você recolher regex e remover todo o espaço em branco)
- IgnoreCase (não necessário)
Expressão regular explicada (em linha)
(?=<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
Você pode tentar isso em A Better .NET Regular Expression Tester .
Eu usei a fonte de amostra 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>
Isso encontrou a correspondência:
<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>
embora realmente tenha saído assim:
<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 fim, gostei muito do artigo de Jeff Atwood: Parsing Html The Cthulhu Way . Engraçado o suficiente, ele cita a resposta a essa pergunta que atualmente tem mais de 4k votos.