Um erro que eu vejo as pessoas fazendo mais e mais uma vez está tentando analisar XML ou HTML com um regex. Aqui estão algumas das razões pelas quais a análise de XML e HTML é difícil:
As pessoas querem tratar um arquivo como uma sequência de linhas, mas isso é válido:
<tag
attr="5"
/>
As pessoas querem tratar a tag <ou <como o início de uma tag, mas coisas desse tipo existem na natureza:
<img src="imgtag.gif" alt="<img>" />
As pessoas geralmente desejam corresponder as tags iniciais às tags finais, mas XML e HTML permitem que as tags se contenham (que as expressões regulares tradicionais não conseguem suportar):
<span id="outer"><span id="inner">foo</span></span>
As pessoas geralmente desejam comparar o conteúdo de um documento (como o famoso problema "encontre todos os números de telefone em uma determinada página"), mas os dados podem ser marcados (mesmo que pareça normal quando visualizados):
<span class="phonenum">(<span class="area code">703</span>)
<span class="prefix">348</span>-<span class="linenum">3020</span></span>
Os comentários podem conter tags mal formatadas ou incompletas:
<a href="foo">foo</a>
<!-- FIXME:
<a href="
-->
<a href="bar">bar</a>
Que outras dicas você conhece?
Respostas:
Aqui está um XML válido e divertido para você:
E este pequeno pacote de alegria é HTML válido:
Sem mencionar toda a análise específica do navegador para construções inválidas.
Boa sorte colocando regex contra isso!
EDIT (Jörg W Mittag): Aqui está outra parte legal do HTML 4.01 bem formado e válido:
fonte
Na realidade
não é HTML válido e também não é XML válido.
Não é um XML válido porque os '<' e '>' não são caracteres válidos dentro das sequências de atributos. Eles precisam ser escapados usando as entidades XML correspondentes & lt; e & gt;
Também não é HTML válido porque o formulário de fechamento curto não é permitido em HTML (mas está correto em XML e XHTML). A tag 'img' também é uma tag implicitamente fechada, conforme a especificação HTML 4.01. Isso significa que o fechamento manual está realmente errado e é equivalente a fechar qualquer outra tag duas vezes.
A versão correta em HTML é
e a versão correta em XHTML e XML é
O exemplo a seguir que você deu também é inválido
Este também não é um HTML ou XML válido. O nome da tag deve estar logo atrás do '<', embora os atributos e o fechamento '>' possam estar onde quiserem. Portanto, o XML válido é realmente
E aqui está outro mais engraçado: você pode realmente optar por usar "ou" como seu atributo entre aspas
Todos os outros motivos postados estão corretos, mas o maior problema com a análise de HTML é que as pessoas geralmente não entendem todas as regras de sintaxe corretamente. O fato de seu navegador interpretar seu grupo de tags como HTML não significa que você realmente escreveu HTML válido.
Edit: E mesmo stackoverflow.com concorda comigo sobre a definição de válido e inválido. Seu XML / HTML inválido não está destacado, enquanto minha versão corrigida é.
Basicamente, o XML não é feito para ser analisado com regexps. Mas também não há razão para fazê-lo. Existem muitos analisadores XML para cada idioma. Você pode escolher entre analisadores SAX, DOM e Pull. É garantido que tudo isso é muito mais rápido que a análise com um regexp e, em seguida, você pode usar tecnologias legais como XPath ou XSLT na árvore DOM resultante.
Minha resposta é, portanto: não apenas é difícil analisar XML com regexps, mas também é uma má idéia. Basta usar um dos milhões de analisadores XML existentes e aproveitar todos os recursos avançados do XML.
HTML é muito difícil de tentar analisar sozinho. Primeiro, a sintaxe legal possui muitas pequenas sutilezas das quais você pode não estar ciente e, em segundo lugar, o HTML em estado selvagem é apenas uma pilha enorme e fedorenta de (você entendeu). Há uma variedade de bibliotecas de analisador lax que fazem um bom trabalho no manuseio de HTML como uma sopa de tags, basta usá-las.
fonte
>
sinal é perfeitamente válido em html stackoverflow.com/questions/94528/…Eu escrevi uma entrada de blog inteira sobre este assunto: Limitações da expressão regular
O cerne da questão é que HTML e XML são estruturas recursivas que exigem mecanismos de contagem para analisar adequadamente. Um regex verdadeiro não é capaz de contar. Você deve ter uma gramática livre de contexto para poder contar.
O parágrafo anterior vem com uma pequena ressalva. Certas implementações de regex agora suportam a ideia de recursão. No entanto, uma vez que você começa a adicionar recursão em suas expressões de expressão regular, você está realmente esticando os limites e deve considerar um analisador.
fonte
Um problema que não está na sua lista é que os atributos podem aparecer em qualquer ordem; portanto, se o seu regex está procurando um link com o href "foo" e a classe "bar", eles podem vir em qualquer ordem e ter qualquer número de outras opções. coisas entre eles.
fonte
Depende do que você quer dizer com "análise". De um modo geral, o XML não pode ser analisado usando regex, pois a gramática XML não é de forma alguma regular. Simplificando, as expressões regulares não podem contar (bem, as expressões regulares Perl podem realmente contar as coisas), portanto, você não pode equilibrar as tags de abertura e fechamento.
fonte
As pessoas estão realmente cometendo um erro usando uma regex ou é simplesmente bom o suficiente para a tarefa que estão tentando realizar?
Concordo totalmente que a análise de html e xml usando um regex não é possível, pois outras pessoas responderam.
No entanto, se o seu requisito não é analisar html / xml, mas apenas obter um pequeno pedaço de dados em um bit "bom" conhecido de html / xml, talvez uma expressão regular ou mesmo uma "substring" ainda mais simples seja boa o suficiente.
fonte
As pessoas normalmente assumem o padrão de escrever padrões gananciosos, o que geralmente leva a um arquivo * não-pensado, arrastando grandes pedaços de arquivo para o maior <foo>. * </foo> possível.
fonte
.*?<
, você pode corrigir isso usando uma classe de caractere negada como[^<]*<
. (Disclaimer: obviamente, isso ainda não é infalível, que é o ponto da questão.)Estou tentado a dizer "não reinvente a roda". Exceto que XML é um formato muito, muito complexo. Então, talvez eu deva dizer "não reinvente o síncrotron".
Talvez o clichê correto comece "quando tudo que você tem é um martelo ..." Você sabe como usar expressões regulares; a expressão regular é boa para analisar, então por que se preocupar em aprender uma biblioteca de análise XML?
Porque a análise de XML é difícil . Qualquer esforço que você economize por não precisar aprender a usar uma biblioteca de análise XML será mais do que compensado pela quantidade de trabalho criativo e correção de erros que você precisará fazer. Para seu próprio bem, pesquise no Google "XML Library" e aproveite o trabalho de outra pessoa.
fonte
Acredito que este clássico tenha as informações que você está procurando. Você pode encontrar o ponto em um dos comentários aqui:
Mais algumas informações da Wikipedia: Hierarquia de Chomsky
fonte
Eu acho que os problemas se resumem a:
O regex quase invariavelmente está incorreto. Existem entradas legítimas que não serão correspondidas corretamente. Se você trabalhar duro o suficiente, poderá torná-lo 99% correto, ou 99,999%, mas torná-lo 100% correto é quase impossível, mesmo que apenas por causa das coisas estranhas que o XML permite usando entidades.
Se o regex estiver incorreto, mesmo para 0,00001% das entradas, você terá um problema de segurança, porque alguém poderá descobrir a entrada que interromperá seu aplicativo.
Se o regex estiver correto o suficiente para cobrir 99,99% dos casos, será completamente ilegível e impossível de manter.
É muito provável que um regex tenha um desempenho muito ruim em arquivos de entrada de tamanho moderado. Meu primeiro encontro com XML foi substituir um script Perl que (incorretamente) analisou documentos XML recebidos por um analisador XML adequado, e não apenas substituímos 300 linhas de código ilegível por 100 linhas que qualquer um podia entender, mas melhoramos o tempo de resposta do usuário de 10 segundos a cerca de 0,1 segundos.
fonte
Discordo. Se você usar recursivo no regex, poderá encontrar facilmente tags de abrir e fechar.
Aqui eu mostrei exemplo de regex para evitar a análise de erros de exemplos na primeira mensagem.
fonte
Dei uma resposta simplificada para esse problema aqui . Embora ela não represente a marca de 100%, explico como é possível se você estiver disposto a fazer algum trabalho de pré-processamento.
fonte