HTML / XML'i ayrıştırmak için normal ifadeyi kullanmak neden mümkün değil: meslekten olmayan terimlerle resmi bir açıklama


117

SO'da HTML veya XML'in normal ifadelerle ayrıştırılmasıyla ilgili soru sorulmadan geçen bir gün yoktur.

Bu görev için normal ifadelerin geçerli olmadığını gösteren örnekler bulmak nispeten kolay olsa da veya kavramı temsil edecek bir ifade koleksiyonuyla SO'da bunun neden layman'da yapılmadığına dair resmi bir açıklama bulamadım. terimleri.

Bu sitede şimdiye kadar bulabildiğim tek resmi açıklama muhtemelen son derece doğru, ama aynı zamanda kendi kendini yetiştiren programcı için oldukça gizemli:

buradaki kusur, HTML'nin bir Chomsky Type 2 dilbilgisi (bağlamdan bağımsız dilbilgisi) ve RegEx'in bir Chomsky Type 3 dilbilgisi (normal ifade) olmasıdır.

veya:

Normal ifadeler yalnızca normal dillerle eşleşebilir, ancak HTML bağlamdan bağımsız bir dildir.

veya:

Sonlu bir otomat (düzenli bir ifadenin altında yatan veri yapısıdır) içinde bulunduğu durumdan ayrı bir belleğe sahip değildir ve eğer keyfi olarak derinlemesine yerleştirmeye sahipseniz, sonlu bir otomat kavramıyla çarpışan rastgele büyük bir otomata ihtiyacınız vardır.

veya:

Normal diller için Pumping lemma, bunu yapamamanızın nedenidir.

[Adil olmak gerekirse: yukarıdaki açıklamaların çoğu wikipedia sayfalarına bağlantılıdır, ancak bunların anlaşılması yanıtların kendilerinden çok daha kolay değildir].

Öyleyse sorum şu: birileri lütfen yukarıda verilen resmi açıklamaların (X) HTML / XML ayrıştırmak için normal ifadenin kullanılmasının mümkün olmadığına dair meslekten olmayan terimlerle bir çeviri sağlayabilir mi?

DÜZENLEME: İlk cevabı okuduktan sonra açıklığa kavuşturmam gerektiğini düşündüm: Çevirmeye çalıştığı kavramları da kısaca açıklayan bir "çeviri" arıyorum : bir cevabın sonunda, okuyucunun kaba bir fikri olmalı - örneğin - "normal dil" ve "bağlamdan bağımsız dilbilgisi" ne anlama geliyor ...


19
Bilgisayar bilimi açısından, "düzenli ifadelerin" günümüz "normal ifade uygulamalarından" (bir programlama dilinde kullandığınız araçlar / API'ler) büyük ölçüde farklı olduğunu unutmayın. İkincisi, karşılaştıkları şeyleri "hatırlayabilir" ve hatta yinelemeli olarak tanımlanmış (alt) kalıplarla eşleşebilir, bu da onları teorik "düzenli ifadelerden" çok daha fazlasını eşleştirebilir / ayrıştırabilir / tanımlayabilir.
Bart Kiers

1
@Bart: Bu gerçekten sadece "normal ifade terimini kötüye kullanan diller için geçerlidir. POSIX ERE tamamen normaldir.
R .. GitHub BUZU DURDURMA

2
@R .., yani, POSIX'e "modern gün uygulaması" diyorsunuz: P. Yine de ciddiyetle: evet, haklısın, bunlar gerçekten düzenli. Dediğim gerekirdi "... ... günümüz regex uygulamalarının çok" ya da "... PCRE ... uygulamalarını regex" .
Bart Kiers

4
Kendilerini cahil programcılara pazarlamak uğruna katı dili temelde kötüye kullanan programlama dillerini ciddiye almakta zorlanıyorum ...
R .. GitHub BUZ YARDIMINI DURDUR

3
@R .., PCRE uygulamalarına "düzenli ifadeler" denmesi talihsiz bir durum, ancak dili ciddiye almamak, onu bir adım öteye götürmek, IMO. Demek istediğim, Perl, Java, Python, Ruby, JavaScript, .NET vb. Bu yüzden ciddi değil mi?
Bart Kiers

Yanıtlar:


117

Şuna konsantre olun:

Sonlu bir otomat (düzenli bir ifadenin altında yatan veri yapısıdır) içinde bulunduğu durumdan ayrı bir belleğe sahip değildir ve eğer keyfi olarak derinlemesine yerleştirmeye sahipseniz, sonlu bir otomat kavramıyla çarpışan rastgele büyük bir otomata ihtiyacınız vardır.

tanım normal ifadelerin dize deseni ile uyumlu olup olmadığını bir test sınırlı bir otomat (her bir desen için bir farklı otomat) tarafından gerçekleştirilebilir gerçeği eşdeğerdir. Sonlu bir otomatın hafızası yoktur - yığın yok, yığın yok, üzerine karalamak için sonsuz bant yok. Sahip olduğu tek şey, her biri test edilmekte olan dizeden bir girdi birimini okuyabilen ve bunu hangi duruma geçileceğine karar vermek için kullanabilen sınırlı sayıda dahili durumdur. Özel durumlar olarak, iki sonlandırma durumu vardır: "evet, eşleşti" ve "hayır, eşleşmedi".

Öte yandan HTML, keyfi olarak derinlemesine iç içe geçebilen yapılara sahiptir. Bir dosyanın geçerli HTML olup olmadığını belirlemek için, tüm kapanış etiketlerinin önceki bir açılış etiketiyle eşleşip eşleşmediğini kontrol etmeniz gerekir. Bunu anlamak için hangi elemanın kapatıldığını bilmeniz gerekir. Hangi açılış etiketlerini gördüğünüzü "hatırlamanın" hiçbir yolu olmadan, şansınız yok.

Bununla birlikte, çoğu "regex" kitaplığının aslında normal ifadelerin katı tanımından daha fazlasına izin verdiğini unutmayın. Geriye dönük referansları eşleştirebiliyorlarsa, normal bir dilin ötesine geçmişlerdir. Bu nedenle, HTML'de bir normal ifade kitaplığı kullanmamanızın nedeni, HTML'nin normal olmadığı basit gerçeğinden biraz daha karmaşıktır.


Burada ayrıca sonlu durum otomatının oldukça iyi bir açıklaması var: youtube.com/watch?v=vhiiia1_hC4
GDP2

55

HTML'nin normal bir dili temsil etmemesi kırmızı ringa balığıdır. Düzenli ifade ve normal diller kulağa benzer ama değil - aynı kökene sahipler, ancak akademik "normal diller" ile motorların mevcut eşleşme gücü arasında dikkate değer bir mesafe var. Aslında, neredeyse tüm modern düzenli ifade motorları normal olmayan özellikleri destekler - basit bir örnek (.*)\1. Bu, tekrarlanan bir karakter dizisini eşleştirmek için geri başvuruyu kullanır - örneğin 123123, veya bonbon. Özyinelemeli / dengeli yapıların eşleştirilmesi, bunları daha da eğlenceli hale getirir.

Wikipedia, Larry Wall'un bir sözünde bunu güzel bir şekilde ifade ediyor :

"Normal ifadeler" [...] gerçek normal ifadelerle yalnızca marjinal olarak ilişkilidir. Yine de, bu terim kalıp eşleştirme motorlarımızın yetenekleriyle büyüdü, bu yüzden burada dilsel zorunlulukla savaşmaya çalışmayacağım. Bununla birlikte, ben bunlara genellikle "normal ifadeler" (veya Anglo-Sakson modundayken "regexen") diyeceğim.

"Normal ifade yalnızca normal dillerle eşleşebilir", görebileceğiniz gibi, genel olarak ifade edilen bir yanlışlıktan başka bir şey değildir.

Öyleyse neden olmasın?

HTML'yi normal ifadeyle eşleştirmemek için iyi bir neden "sırf yapabilmeniz gerektiği anlamına gelmemesidir". Mümkün olsa da - iş için daha iyi araçlar var . Düşünen:

  • Geçerli HTML, düşündüğünüzden daha zor / karmaşıktır.
  • Birçok "geçerli" HTML türü vardır - örneğin HTML'de geçerli olan, XHTML'de geçerli değildir.
  • İnternette bulunan serbest biçimli HTML'nin çoğu zaten geçerli değil . HTML kitaplıkları bunlarla da başa çıkmak için iyi bir iş çıkarır ve bu yaygın durumların çoğu için test edilmiştir.
  • Çoğu zaman, bir bütün olarak ayrıştırmadan verilerin bir bölümünü eşleştirmek imkansızdır. Örneğin, tüm başlıkları arıyor olabilirsiniz ve sonunda bir yorumun veya bir dize değişmezinin içinde eşleşiyor olabilirsiniz. <h1>.*?</h1>ana başlığı bulmak için cesur bir girişim olabilir, ancak şunu bulabilir:

    <!-- <h1>not the title!</h1> -->

    Ya da:

    <script>
    var s = "Certainly <h1>not the title!</h1>";
    </script>

Son nokta en önemlisidir:

  • Özel bir HTML ayrıştırıcı kullanmak, bulabileceğiniz herhangi bir normal ifadeden daha iyidir. Çoğu zaman, XPath ihtiyacınız olan verileri bulmanın daha iyi ifade edici bir yolunu sağlar ve bir HTML ayrıştırıcı kullanmak çoğu insanın düşündüğünden çok daha kolaydır .

Konunun iyi bir özeti ve Regex ile HTML'nin karıştırılmasıyla ilgili önemli bir yorum Jeff Atwood'un blogunda bulunabilir: Parsing Html The Cthulhu Way .

HTML'yi ayrıştırmak için normal bir ifade kullanmak ne zaman daha iyidir?

Çoğu durumda, bir kitaplığın size verebileceği DOM yapısında XPath kullanmak daha iyidir. Yine de, popüler görüşün aksine, ayrıştırıcı kitaplığı değil de normal ifade kullanmanızı şiddetle tavsiye ettiğim birkaç durum var:

Bu koşullardan birkaçı göz önüne alındığında:

  • HTML dosyalarınız için tek seferlik bir güncelleme yapmanız gerektiğinde ve yapının tutarlı olduğunu bilirsiniz.
  • Çok küçük bir HTML kod parçasına sahip olduğunuzda.
  • Bir HTML dosyasıyla değil, benzer bir şablon oluşturma motoruyla uğraşmadığınızda (bu durumda bir ayrıştırıcı bulmak çok zor olabilir).
  • HTML'nin parçalarını değiştirmek istediğinizde, ancak hepsini değiştirmediğinizde - bildiğim kadarıyla bir ayrıştırıcı bu isteği yanıtlayamaz: tüm belgeyi ayrıştıracak ve asla değiştirmek istemediğiniz bölümleri değiştirerek tüm belgeyi kaydedecektir.

4
Bu, HTML'yi ayrıştırmak için regex'in ne zaman kullanılacağına (kullanılmayacağına) dair çok açık ve güzel yazılmış bir parçadır, ancak soruma pek cevap vermiyor. Onun yerine bu soruya geçmenizi önerebilir miyim ? Sanırım orada daha fazla itibar kazanacaksınız ama - hepsinden önemlisi - burası gelecekteki ziyaretçilerin onu daha alakalı bulacağı bir yer olacağını düşünüyorum (@Bart Kiers'ın soruma ziyaretçilere "ekstra gücü" hatırlatan bir yorumu var. modern normal ifade motorları).
mac

1
@mac - Çok teşekkürler. Aslında biraz düşündüm. Sorunuza cevap vermediğimi biliyorum, ama sorunun temelde doğru olduğunu düşünmüyorum - yanlış nedeni açıklamayı istiyorsunuz ... Yine de iyi bir fikriniz var, belki diğer soru daha uygundur ...
Kobi

19

Çünkü HTML sınırsız yuvalanmaya sahip <tags><inside><tags and="<things><that><look></like></tags>"></inside></each></other>olabilir ve normal ifade bununla gerçekten başa çıkamaz çünkü içeri girdiği ve çıktığı şeyin geçmişini izleyemez.

Zorluğu gösteren basit bir yapı:

<body><div id="foo">Hi there!  <div id="bar">Bye!</div></div></body>

Genelleştirilmiş normal ifade tabanlı ayıklama rutinlerinin% 99,9'u , bu div'in kapanış etiketini div'in kapanış etiketinden ayıramadıkları için divkimliğin içindeki her şeyi bana doğru şekilde veremez . Bunun nedeni, "tamam, şimdi iki div'in ikincisine indim, bu yüzden gördüğüm bir sonraki div kapanış beni birinden geri getiriyor ve ondan sonraki, ilkinin kapanış etiketi" demenin bir yolu olmamasıdır. . Programcılar tipik olarak, belirli bir durum için özel durum normal ifadeleri tasarlayarak yanıt verirler; bu, daha fazla etiket içeriye girdiği anda bozulur ve zaman açısından muazzam bir maliyetle ve hayal kırıklığı ile anlaşılmaması gerekir. İşte bu yüzden insanlar her şeye kızıyor.foobarfoo


1
Cevabı takdir ediyorum, ancak sorum "regex'i neden kullanamıyorum ..." değil. Sorum, verdiğim resmi açıklamaları "tercüme etmek" ile ilgili! :)
mac

5
Bu, bir anlamda hepsinin bir çevirisidir, en yakın olarak "Normal ifadeler yalnızca normal dillerle eşleşebilir, ancak HTML bağlamdan bağımsız bir dildir" ve sonlu otomata hakkındadır. Gerçekten hepsi aynı sebep.
Ianus Chiaroscuro

Üzgünüm, belki sorumda net olamadım (iyileştirme önerilerine açığız!). Ama aynı zamanda "çeviriyi" de açıklayan bir cevap arıyorum. Cevabınız ne 'normal dil' ne de 'bağlamdan bağımsız dil' kavramlarını netleştirmiyor ...
mac

5
Bu terimleri açıklamak, jargonun kendisi kadar teknik ve tüm hassas dilin ulaştığı gerçek anlamdan, yani benim yazdığım şeyden bir dikkat dağıtıcı olacaktır.
Ianus Chiaroscuro

4
<(\w+)(?:\s+\w+="[^"]*")*>(?R)*</\1>|[\w\s!']+kod örneğinizle eşleşir.
Kobi

9

Normal bir dil, sonlu bir durum makinesi tarafından eşleştirilebilen bir dildir.

(Sonlu Durum makinelerini, Aşağı itme makinelerini ve Turing makinelerini anlamak, temelde dördüncü sınıf bir üniversite CS Kursunun müfredatıdır.)

"Hi" dizesini tanıyan aşağıdaki makineyi düşünün.

(Start) --Read h-->(A)--Read i-->(Succeed)
  \                  \
   \                  -- read any other value-->(Fail) 
    -- read any other value-->(Fail)

Bu, normal bir dili tanımak için basit bir makinedir; Parantez içindeki her ifade bir durumdur ve her ok bir geçiştir. Bunun gibi bir makine inşa etmek, herhangi bir girdi dizesini normal bir dile karşı test etmenize olanak sağlar - dolayısıyla düzenli bir ifade.

HTML, hangi durumda olduğunuzdan daha fazlasını bilmenizi gerektirir - etiket iç içe yerleştirmeyle eşleşmek için daha önce gördüklerinizin geçmişini gerektirir. Makineye bir yığın eklerseniz bunu başarabilirsiniz, ancak bu durumda artık "normal" olmaz. Buna Aşağı itilen makine denir ve bir dilbilgisini tanır.


2
"Sonlu Durum makinelerini, Aşağı itme makinelerini ve Turing makinelerini anlamak, temelde 300 seviyeli bir CS Kursunun müfredatıdır." Bunun, konunun ne kadar zor / ileri olduğunu belirtme çabası olduğunu anlıyorum, ancak bahsettiğiniz okul sistemine aşina değilim, lütfen ülkeye özgü olmayan bir şekilde açıklar mısınız? Teşekkür ederim! :)
mac

1
Onu güncelledim. Sadece bir yığın taşması gönderisinde açıklamak için anlaşılmasının çok zor olduğunu bilmiyorum.
Sean McMillan

6

Normal bir ifade, sonlu (ve genellikle oldukça küçük) sayıda ayrık duruma sahip bir makinedir.

XML, C veya başka herhangi bir dili dil öğelerinin keyfi olarak yerleştirilmesiyle ayrıştırmak için ne kadar derin olduğunuzu hatırlamanız gerekir. Yani, parantezleri / köşeli parantezleri / etiketleri sayabilmelisiniz.

Sonlu bellek ile sayamazsınız. Durumunuzdan daha fazla kuşak seviyesi olabilir! Dilinizin iç içe geçme düzeylerinin sayısını kısıtlayan bir alt kümesini ayrıştırabilirsiniz, ancak bu çok sıkıcı olacaktır.


6

Dilbilgisi, kelimelerin nereye gidebileceğinin resmi bir tanımıdır. Örneğin, sıfatlar isimlerden önce gelir in English grammar, ancak isimleri takip ederen la gramática española . Bağlamdan bağımsız, gramerin tüm bağlamlarda evrensel olduğu anlamına gelir. Bağlama duyarlı, belirli bağlamlarda ek kurallar olduğu anlamına gelir.

C #, örneğin, usingbir şey farklı yollardan using System;daha dosyaların üstündeki using (var sw = new StringWriter (...)). Daha alakalı bir örnek, kod içindeki aşağıdaki koddur:

void Start ()
{
    string myCode = @"
    void Start()
    {
       Console.WriteLine (""x"");
    }
    ";
}

Bu anlaşılabilir bir cevap
A Kişi

Ancak bağlamdan bağımsız, düzenli anlamına gelmez. Eşleşen parantezlerin dili bağlamdan bağımsızdır, ancak normal değildir.
Taemyr

Eklenmesi gereken şey, düzenli ifadelerin (Perl'de mevcut olan uzantıları eklemediğiniz sürece) normal gramerlere eşdeğer olmasıdır; bu, keyfi olarak derin dengelenmiş parantezler veya HTML öğesi açma ve kapama etiketleri gibi keyfi olarak derinlemesine iç içe geçmiş yapıları tanımlayamayacakları anlamına gelir.
reinierpost

4

XML ve HTML'yi ayrıştırmak için bilgisayar bilimi teorisiyle hiçbir ilgisi olmayan normal ifadeleri kullanmamanın başka bir pratik nedeni daha var: normal ifadeniz ya çok karmaşık olacak ya da yanlış olacaktır.

Örneğin, eşleşecek bir normal ifade yazmak çok iyi

<price>10.65</price>

Ancak kodunuz doğru olacaksa, o zaman:

  • Hem başlangıç ​​hem de bitiş etiketinde öğe adından sonra boşluğa izin vermelidir

  • Belge bir ad alanındaysa, herhangi bir ad alanı önekinin kullanılmasına izin vermelidir

  • Muhtemelen başlangıç ​​etiketinde görünen tüm bilinmeyen özniteliklere izin vermeli ve yok saymalıdır (belirli sözlüğün anlam bilgisine bağlı olarak)

  • Ondalık değerden önce ve sonra beyaz boşluklara izin vermesi gerekebilir (yine, belirli XML sözlüğünün ayrıntılı kurallarına bağlı olarak).

  • Öğe gibi görünen ancak aslında bir yorum veya CDATA bölümünde bulunan bir şeyle eşleşmemelidir (bu, özellikle ayrıştırıcınızı kandırmaya çalışan kötü amaçlı verilerin olasılığı varsa önemlidir).

  • Giriş geçersizse teşhis sağlaması gerekebilir.

Elbette bunların bir kısmı, uyguladığınız kalite standartlarına bağlıdır. StackOverflow'da, belirli bir şekilde XML oluşturmak zorunda olan (örneğin, etiketlerde boşluk olmadan) birçok sorun görüyoruz çünkü belirli bir şekilde yazılmasını gerektiren bir uygulama tarafından okunuyor. Kodunuzun herhangi bir uzun ömürlülüğü varsa, kodunuzu test ettiğiniz tek bir örnek giriş belgesini değil, XML standardının izin verdiği herhangi bir şekilde yazılmış gelen XML'i işleyebilmesi önemlidir.


2

Tamamen teorik anlamda, normal ifadelerin XML'i ayrıştırması imkansızdır. Önceki durumları hatırlamalarına izin vermeyecek şekilde tanımlanırlar, böylece rastgele bir etiketin doğru eşleşmesini önlerler ve iç içe yerleştirmenin normal ifadede yerleşik olması gerekeceğinden rastgele bir iç içe geçme derinliğine giremezler.

Bununla birlikte, modern normal ifade ayrıştırıcıları, kesin bir tanıma bağlılıkları yerine geliştiriciye yardımcı olmaları için oluşturulmuştur. Bu nedenle, önceki durumların bilgisinden yararlanan geri referanslar ve özyineleme gibi şeylere sahibiz. Bunları kullanarak, XML'i keşfedebilen, doğrulayabilen veya ayrıştırabilen bir normal ifade oluşturmak oldukça basittir.

Örneğin düşünün,

(?:
    <!\-\-[\S\s]*?\-\->
    |
    <([\w\-\.]+)[^>]*?
    (?:
        \/>
        |
        >
        (?:
            [^<]
            |
            (?R)
        )*
        <\/\1>
    )
)

Bu, bir sonraki düzgün biçimlendirilmiş XML etiketini veya açıklamayı bulacaktır ve yalnızca içeriğinin tamamı uygun şekilde biçimlendirilmişse onu bulacaktır. (Bu ifade, PCRE'ye çok yakın olan Boost C ++ 'ın normal ifade kitaplığını kullanan Notepad ++ kullanılarak test edilmiştir.)

Şu şekilde çalışır:

  1. İlk parça bir yorumla eşleşir. Bunun önce gelmesi gerekir, böylece aksi halde takılmalara neden olabilecek herhangi bir yorumlanmış kodla ilgilenir.
  2. Bu eşleşmezse, bir etiketin başlangıcını arayacaktır. Adı yakalamak için parantez kullandığını unutmayın.
  3. Bu etiket ya bir ile biter ve />böylece etiketi tamamlar ya da bir ile biter >, bu durumda etiketin içeriğini inceleyerek devam eder.
  4. Bir ulaşana kadar ayrıştırmaya devam edecek < ve bu noktada ifadenin başına dönerek ya bir yorum ya da yeni bir etiketle başa çıkmasına izin verecektir.
  5. Metnin sonuna veya <ayrıştıramayacağı bir yere gelene kadar döngü boyunca devam edecektir . Eşleşmemek elbette sürecin yeniden başlamasına neden olacaktır. Aksi takdirde, <muhtemelen bu yineleme için kapanış etiketinin başlangıcıdır. Bir kapanış etiketi içindeki arka referansı kullanarak, <\/\1>geçerli yineleme (derinlik) için açılış etiketiyle eşleşir. Sadece bir yakalama grubu var, bu yüzden bu maç basit bir mesele. Bu onu kullanılan etiketlerin adlarından bağımsız kılar, ancak gerekirse yakalama grubunu yalnızca belirli etiketleri yakalayacak şekilde değiştirebilirsiniz.
  6. Bu noktada ya bir sonraki seviyeye kadar mevcut özyinelemeden çıkar ya da bir maçla biter.

Bu örnek, boşluklarla ilgili sorunları çözer veya yalnızca olumsuzlayan karakter gruplarını kullanarak <veya >veya yorumlar söz konusu olduğunda, [\S\s]tek satırda bile satır başları ve yeni satırlar da dahil olmak üzere herhangi bir şeyle eşleşecek olanı kullanarak. modu, a ulaşana kadar devam eder -->. Bu nedenle, anlamlı bir şeye ulaşana kadar her şeyi geçerli kabul eder.

Çoğu amaç için, bunun gibi bir normal ifade pek kullanışlı değildir. XML'in düzgün bir şekilde biçimlendirildiğini doğrulayacaktır, ancak gerçekten yapacak olan budur ve özellikleri hesaba katmaz (bu kolay bir ekleme olsa da). Bu sadece bu kadar basit çünkü bunun gibi gerçek dünya sorunlarını ve etiket adlarının tanımlarını dışarıda bırakıyor. Gerçek kullanım için takmak, onu çok daha canavar haline getirir. Genel olarak, gerçek bir XML ayrıştırıcı çok daha üstündür. Bu, muhtemelen özyinelemenin nasıl çalıştığını öğretmek için en uygun olanıdır.

Uzun lafın kısası: Gerçek iş için bir XML ayrıştırıcı kullanın ve normal ifadelerle oynamak istiyorsanız bunu kullanın.


3
Bu regex'in yalnızca girdinin doğru biçimlendirilmesi durumunda eşleşeceği ifadesi yanlıştır. İsimlerin geçerli XML isimleri olup olmadığını kontrol etmez, öznitelikleri kontrol etmez, varlık ve karakter referanslarını kontrol etmez, CDATA veya işleme talimatlarını işlemez. Test edildi dediğinizde, XML uygunluk test paketine benzer herhangi bir şey üzerinde test edildiğinden çok şüpheliyim. Şimdiye kadar gördüğüm normal ifadelerle XML işleme girişimlerinin hepsinde sorun budur: az sayıda girdiyle çalışırlar, ancak yasal olarak uygulamanıza aktarılabilen herhangi bir XML ile çalışmazlar.
Michael Kay

2
Ayrıca, normal ifadenin eşleşmediği iyi biçimlendirilmiş girdiler vardır. Örneğin, bitiş etiketindeki addan sonra beyaz boşluğa izin vermez. Bu hataların çoğu kolayca düzeltilebilir, ancak TÜM hataları düzelttikten sonra tamamen kullanılamaz bir şeyle sonuçlanırsınız. Ve tabii ki gerçek anlam, bir ayrıştırıcının size bir evet / hayır cevabı vermesini değil, kendisiyle yararlı bir şey yapan bir uygulamaya bilgi aktarmasını istemenizdir.
Michael Kay

0

XML / HTML'yi düzenli ifade ile ayrıştırmayın, uygun bir XML / HTML ayrıştırıcı ve güçlü bir sorgu.

teori:

Derleme teorisine göre, XML / HTML, sonlu durum makinesine dayalı normal ifade kullanılarak ayrıştırılamaz . XML / HTML'nin hiyerarşik yapısı nedeniyle, bir aşağı açılan otomat kullanmanız ve YACC gibi bir araç kullanarak LALR dilbilgisini düzenlemeniz gerekir .

realLife © ® ™ günlük araç :

Aşağıdakilerden birini kullanabilirsiniz:

xmllint genellikle varsayılan olarak libxml2xpath1 ile yüklenir ( yeni satırlarla ayrılmış çıktı için sarmalayıcımı kontrol edin

xmlstarlet düzenleyebilir, seçebilir, dönüştürebilir ... Varsayılan olarak kurulu değil, xpath1

xpath , perl modülü XML :: XPath, xpath1 aracılığıyla yüklendi

xidel xpath3

saxon-lint kendi projem, @Michael Kay's Saxon-HE Java kütüphanesi, xpath3

veya yüksek seviyeli dilleri ve uygun kitaplıkları kullanabilirsiniz, diye düşünüyorum:

's lxml( from lxml import etree)

s' XML::LibXML, XML::XPath, XML::Twig::XPath,HTML::TreeBuilder::XPath

, bu örneğe bakın

DOMXpath, bu örneğe bakın


Kontrol edin: HTML etiketleriyle normal ifadeler kullanma

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.