XML ve özellikle HTML'yi ayrıştırmak için doğru aracın normal ifade motoru değil ayrıştırıcı olduğunu kabul ediyorum . Ancak, diğerlerinin de belirttiği gibi, bazen normal ifadeyi kullanmak daha hızlı, daha kolaydır ve veri biçimini biliyorsanız işi yapar.
Microsoft aslında .NET Framework'te Düzenli İfadeler için En İyi Yöntemler bölümüne sahiptir ve özellikle Giriş Kaynağını düşünün .
Normal İfadelerin sınırlamaları vardır, ancak aşağıdakileri düşündünüz mü?
.NET çerçevesi Dengeleme Grubu Tanımlarını desteklemesi bakımından düzenli ifadeler söz konusu olduğunda benzersizdir .
Bu nedenle XML'yi düzenli ifadeler kullanarak ayrıştırabileceğinize inanıyorum. Bununla birlikte, geçerli bir XML olması gerektiğini unutmayın ( tarayıcılar HTML'yi çok affediyor ve HTML içinde kötü XML sözdizimine izin veriyor ). "Dengeleme Grubu Tanımı", normal ifade motorunun PDA gibi davranmasına izin vereceğinden bu mümkündür.
Yukarıda belirtilen 1. maddeden alıntı:
.NET Düzenli İfade Motoru
Yukarıda tarif edildiği gibi düzgün şekilde dengelenmiş yapılar, normal bir ifade ile tarif edilemez. Ancak, .NET normal ifade motoru dengeli yapıların tanınmasına izin veren birkaç yapı sağlar.
(?<group>)
- yakalanan sonucu ad grubuyla yakalama yığınına iter.
(?<-group>)
- yakalama yığından ad grubuyla en fazla yakalamayı açar.
(?(group)yes|no)
- isim grubuna sahip bir grup varsa evet kısmı ile eşleşir, aksi takdirde hiçbir parça ile eşleşmez.
Bu yapılar, .NET normal ifadesinin, yığın işlemlerinin basit sürümlerine izin vererek kısıtlı bir PDA'yı taklit etmesine izin verir: push, pop ve empty. Basit işlemler, sırasıyla artış, azalma ve sıfıra eşittir. Bu, .NET normal ifade motorunun bağlamdan bağımsız dillerin bir alt kümesini, özellikle de yalnızca basit bir sayaç gerektirenleri tanımasını sağlar. Bu da geleneksel olmayan .NET düzenli ifadelerinin düzgün şekilde dengelenmiş yapıları tanımasını sağlar.
Aşağıdaki normal ifadeyi düşünün:
(?=<ul\s+id="matchMe"\s+type="square"\s*>)
(?>
<!-- .*? --> |
<[^>]*/> |
(?<opentag><(?!/)[^>]*[^/]>) |
(?<-opentag></[^>]*[^/]>) |
[^<>]*
)*
(?(opentag)(?!))
Bayrakları kullanın:
- Tek çizgi
- IgnorePatternWhitespace (normal ifadeyi daraltırsanız ve tüm boşlukları kaldırırsanız gerekli değildir)
- IgnoreCase (gerekli değil)
Düzenli İfade Açıklaması (satır içi)
(?=<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
Bunu A Better .NET Regular Expression Tester'da deneyebilirsiniz .
Örnek kaynağını kullandım:
<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>
Bu eşleşmeyi buldu:
<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>
aslında bu şekilde ortaya çıkmasına rağmen:
<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>
Son olarak, Jeff Atwood'un Html Cthulhu Yolu Ayrıştırma makalesinden gerçekten keyif aldım . Yeterince komik, şu anda 4k'den fazla oyu olan bu sorunun cevabını gösteriyor.