SAX ve DOM arasındaki fark nedir?


242

XML ayrıştırıcıları hakkında bazı makaleler okudum ve SAX ve DOM ile karşılaştım .

SAX olay tabanlıdır ve DOM ağaç modelidir - bu kavramlar arasındaki farkları anlamıyorum.

Anladığım kadarıyla, olay temelli, düğüme bir tür olay gerçekleştiği anlamına gelir. Biri belirli bir düğümü tıklattığında olduğu gibi, tüm düğümleri aynı anda yüklemek yerine tüm alt düğümleri verecektir. Ancak DOM ayrıştırma durumunda, tüm düğümleri yükler ve ağaç modelini yapar.

Anlayışım doğru mu?

Lütfen beni düzeltin Yanılıyorsam veya olay tabanlı ve ağaç modelini daha basit bir şekilde açıklarsam.


Düzgün bir şekilde konuşmak bir DOM ayrıştırıcı değildir. Belirli bir DOM tabanlı yazılım, biçimlendirme ayrıştırma işlemine sahip olabilir veya olmayabilir ve çoğu HTML DOM yazılımı içerir. Ancak bir DOM, herhangi bir serileştirme formatıyla ilişkilendirilemeyecek tamamen ayrı bir şeydir.
Bob77

Yanıtlar:


305

Yakınsın.

SAX'ta, XML ayrıştırılırken olaylar tetiklenir . Ayrıştırıcı XML'yi ayrıştırırken ve başlayarak bir etiketle karşılaştığında (ör. <something>), tagStartedEtkinliği tetikler ( etkinliğin gerçek adı farklı olabilir). Benzer şekilde, etiket ayrıştırılırken ( </something>) karşılandığında , tetiklenir tagEnded. Bir SAX ayrıştırıcısı kullanmak, bu olayları işlemeniz ve her olayla birlikte döndürülen verileri anlamanız gerektiğini belirtir.

DOM'de, ayrıştırma sırasında tetiklenen hiçbir etkinlik yoktur. Tüm XML ayrıştırılır ve bir DOM ağacı (XML'deki düğümlerin) oluşturulur ve döndürülür. Ayrıştırıldıktan sonra, kullanıcı daha önce XML'deki çeşitli düğümlere gömülü olan çeşitli verilere erişmek için ağaçta gezinebilir.

Genel olarak, DOM'un kullanımı daha kolaydır, ancak kullanmaya başlamadan önce tüm XML'yi ayrıştırma yükü vardır.


135
+1 - netleştirmek için: RAM'e sığacak daha küçük dosyalara sahip bir DOM ayrıştırıcı kullanın. Alışılmayacak büyük dosyalar için SAX ayrıştırıcı kullanın.
Richard H

teşekkürler @spartkymat. Ancak SAX olay tabanlı olması durumunda, SAX ayrıştırıcısı belirli bir alt düğümün belirli bir üst öğenin alt öğesi olduğunu bilebilir mi? Yoksa basitçe ayrışacak mı? Örneğin. bir <şirketim> var ve çocuk <işçi>. Peki bu durumda bu şirket ve çalışan ayrıştırılacak mı yoksa şirketin çalışanın ebeveyni olduğu ilişkisini gösterecek mi?
user414967

4
Sadece ayrıştırılacaktır. Bu tür bilgileri kendiniz saklamanız gerekecektir (bir devlet makinesi aracılığıyla veya başka bir şekilde). Bir DOM ayrıştırıcı kullanmak için daha fazla neden (kaynaklar izin veriyorsa) :-).
sparkymat

1
@Richard H XML dosyalarını kullanan herkesin RAM'e sığmayacak kadar büyük olduğunu iddia ediyorum ki çok çok yanlış bir şey yapıyor.
antred

1
40 m büyüklüğünde bir excel yükleyin, SAX ayrıştırıcı kullanırken 200m bellek kullanın, ancak DOM ayrıştırıcı kullanırken 9g bellek kullanın.
zhiyuan_

98

Birkaç kelimeyle ...

SAX ( S uygu bir için PI X ML) bir akım bazlı işlemcidir. Herhangi bir zamanda bellekte sadece küçük bir parçanız vardır ve XML akışı " tagStarted()vb. ağaçlar.

DOM ( D ocument O Nesne M odel): Sen belleğe her şeyi yüklemek - bu büyük bir bellek domuz var. Orta büyüklükteki belgelerle bile belleği patlatabilirsiniz. Ama xpath kullanabilir ve ağacı vb. Geçebilirsiniz.


66

Burada daha basit kelimelerle:

DOM

  • Ağaç modeli ayrıştırıcısı (Nesne tabanlı) (Düğüm ağacı).

  • DOM dosyayı belleğe yükler ve sonra dosyayı ayrıştırır.

  • Ayrıştırmadan önce tüm XML dosyasını yüklediğinden bellek kısıtlamaları vardır.

  • DOM okunur ve yazılır (düğüm ekleyebilir veya silebilir).

  • XML içeriği küçükse, DOM ayrıştırıcısını tercih edin.

  • Etiketleri aramak ve etiketlerin içindeki bilgileri değerlendirmek için ileri ve geri arama yapmak mümkündür. Bu, navigasyon kolaylığı sağlar.

  • Çalışma zamanında daha yavaştır.

SAX

  • Olay tabanlı ayrıştırıcı (Olay sırası).

  • SAX dosyayı okurken ayrıştırır, yani düğümü düğüme göre ayrıştırır.

  • XML içeriğini bellekte saklamadığından bellek kısıtlaması yoktur.

  • SAX salt okunurdur, yani düğümü ekleyemez veya silemez.

  • Bellek içeriği büyük olduğunda SAX ayrıştırıcısını kullanın.

  • SAX, XML dosyasını yukarıdan aşağıya doğru okur ve geriye doğru gezinme mümkün değildir.

  • Çalışma zamanında daha hızlı.


mükemmel ... bazı cevaplar bekliyordum. İyi iş :)
Kunal Gupta

37

DOM tabanlı modeli anlama konusunda haklısınız. XML dosyası bir bütün olarak yüklenecek ve tüm içeriği belgenin temsil ettiği ağacın bellek içi bir temsili olarak oluşturulacaktır. Bu, girdi dosyasının büyüklüğüne bağlı olarak zaman ve bellek tüketebilir. Bu yaklaşımın yararı, belgenin herhangi bir bölümünü kolayca sorgulayabilmeniz ve ağaçtaki tüm düğümleri serbestçe değiştirebilmenizdir.

DOM yaklaşımı genellikle, yüklendikten sonra farklı şekillerde değiştirilmesi ve sorgulanması gerekebilecek küçük XML yapıları (platformun sahip olduğu beygir gücüne ve belleğe bağlıdır) için kullanılır.

Öte yandan SAX, neredeyse her boyuttaki XML girişini işlemek için tasarlanmıştır. Belgenin yapısını bulmak ve tüm düğümler, öznitelikler vb. İçin potansiyel olarak çok sayıda nesne hazırlamak için XML çerçevesini yerine getirmek yerine, SAX bunu tamamen size bırakır.

Temel olarak yaptığı şey üstten girişi okumak ve belirli "olaylar" meydana geldiğinde sağladığınız geri arama yöntemlerini çağırmaktır. Bir etkinlik, bir açılış etiketine, etiketteki bir özelliğe isabet ediyor, bir öğenin içindeki metni buluyor veya bir bitiş etiketiyle karşılaşıyor olabilir.

SAX, girişi inatla okur ve size bu şekilde gördüklerini anlatır. İhtiyacınız olan tüm durum bilgisini korumak size bağlıdır. Genellikle bu bir tür devlet makinesi inşa edeceğiniz anlamına gelir.

XML işleme için bu yaklaşım çok daha sıkıcı olsa da, çok güçlü olabilir. Bir blog özet akışından haber makalelerinin başlıklarını çıkarmak istediğinizi düşünün. Bu XML'i DOM kullanarak okursanız, XML'de bulunan tüm makale içeriklerini, tüm görüntüleri vb.

SAX ile, "startTag" olay yönteminiz her çağrıldığında öğe adının (ör. "" Başlık "olup olmadığını kontrol edebilirsiniz. Öyleyse, bir sonraki "elementText" etkinliğinin size sunduğu her şeyi eklemeniz gerektiğini bilirsiniz. "EndTag" olay çağrısını aldığınızda, bunun "title" öğesinin kapanış öğesi olup olmadığını tekrar kontrol edersiniz. Bundan sonra, giriş sona erene veya "başlık" adında başka bir "startTag" gelene kadar diğer tüm öğeleri yok sayabilirsiniz. Ve bunun gibi...

Megabayt ve megabaytlık XML'i bu şekilde okuyabilir, ihtiyacınız olan küçük miktarda veriyi çıkarabilirsiniz.

Bu yaklaşımın olumsuz tarafı, elbette, hangi verileri çıkarmanız gerektiğine ve XML yapısının ne kadar karmaşık olduğuna bağlı olarak, kendinizi çok daha fazla kitap tutmanız gerektiğidir. Ayrıca, XML ağacının yapısını doğal olarak değiştiremezsiniz, çünkü asla bir bütün olarak elinizde yoktur.

Bu nedenle, genel olarak SAX, belirli bir "sorgu" göz önünde bulundurularak aldığınız potansiyel olarak büyük miktarda veriyi taramak için uygundur, ancak değişiklik yapmanıza gerek yoktur, ancak DOM size daha pahalı bir yapı ve içerik değiştirme konusunda tam esneklik sağlamayı amaçlamaktadır. daha yüksek kaynak talebi.


16

Elmaları ve armutları karşılaştırıyorsunuz. SAX, serileştirilmiş DOM yapılarını ayrıştıran bir ayrıştırıcıdır . Birçok farklı ayrıştırıcı vardır ve "olay tabanlı" ayrıştırma yöntemini ifade eder.

Belki küçük bir özet:

  • Doküman nesne modeli (DOM) hiyerarşik, ağaç bazlı belge yapısını açıklayan bir soyut veri modeli; bir belge ağacı düğümlerden oluşur : eleman, nitelik ve metin düğümleri (ve diğerleri). Düğümlerin ebeveynleri, kardeşleri ve çocukları vardır ve JavaScript'ten alıştığınız tüm şeyler (bu arada DOM ile bir ilgisi yoktur).

  • Bir DOM yapısı, HTML veya XML gibi bir biçimlendirme dili kullanılarak serileştirilebilir , yani bir dosyaya yazılabilir. Böylece bir HTML veya XML dosyası soyut bir belge ağacının "yazılı" veya "düzleştirilmiş" versiyonunu içerir.

  • Bir bilgisayarın bir DOM ağacını bir dosyadan işlemesi, hatta görüntülemesi için dosyanın serisini kaldırması veya ayrıştırması ve bellekteki soyut ağacı yeniden yapılandırması gerekir. Ayrıştırma devreye giriyor.

Şimdi ayrıştırıcıların doğasına geliyoruz. Ayrıştırmanın bir yolu, belgenin tamamını okumak ve bellekte bir ağaç yapısını tekrar tekrar oluşturmak ve son olarak tüm sonucu kullanıcıya açıklamaktır. (Sanırım bu ayrıştırıcıları "DOM ayrıştırıcıları" diyebiliriz.) Bu kullanıcı için çok kullanışlı olurdu (PHP'nin XML ayrıştırıcısının yaptığı şey budur), ancak ölçeklenebilirlik sorunlarından muzdarip ve büyük belgeler için çok pahalı hale geliyor.

Öte yandan, SAX tarafından yapılan şekilde olay tabanlı ayrıştırma, dosyaya doğrusal olarak bakar ve "bu öğe başlatıldı" gibi yapısal bir veri parçasıyla karşılaştığında kullanıcıya geri arama yapar , bu öğe sona erdi " , "burada bazı metinler" vb. Bu, girdi dosya boyutu için endişe duymadan sonsuza kadar devam edebileceği avantajına sahiptir, ancak kullanıcının tüm gerçek işleme işini yapmasını gerektirir (sağlayarak )-sırtlarını diyoruz. Orijinal sorunuza geri dönmek için "olay tabanlı" terimi , ayrıştırıcının XML dosyasını geçerken yükselttiği olayları ayrıştırır.

Wikipedia makalesi SAX ayrıştırma aşamaları üzerinde birçok detay vardır.


11

Bu soru için genel soru-cevap odaklı cevap vereceğim:

Soruların Cevabı

Neden XML ayrıştırıcısına ihtiyacımız var?

XML ayrıştırıcıya ihtiyacımız var çünkü uygulamamızdaki her şeyi sıfırdan yapmak istemiyoruz ve çok düşük seviyeli ama bizim için çok gerekli bir şey yapmak için bazı "yardımcı" programlara veya kütüphanelere ihtiyacımız var. Bu düşük seviyeli ancak gerekli şeyler iyi biçimlendirmeyi kontrol etmek, dokümanı DTD veya şemasına göre doğrulamak (sadece ayrıştırıcıları doğrulamak için), karakter referansını çözümlemek, CDATA bölümlerini anlamak vb. XML ayrıştırıcıları sadece böyle "yardımcı" programlar ve tüm bu işleri yapacaklar. XML ayrıştırıcıyla, bu karmaşıklıkların çoğundan korunuyoruz ve ayrıştırıcılar tarafından uygulanan API'ler aracılığıyla kendimizi sadece yüksek düzeyde programlama yapmaya konsantre edebiliriz ve böylece programlama verimliliği elde edebiliriz.

Hangisi daha iyi, SAX veya DOM?

Hem SAX hem de DOM ayrıştırıcının avantajları ve dezavantajları vardır. Hangisinin daha iyi olduğu, başvurunuzun özelliklerine bağlı olmalıdır (lütfen aşağıdaki bazı sorulara bakın).

Hangi ayrıştırıcı daha iyi hız, DOM veya SAX ayrıştırıcıları alabilir?

SAX ayrıştırıcı daha iyi hız elde edebilirsiniz.

Ağaç tabanlı API ile etkinlik tabanlı API arasındaki fark nedir?

Ağaç tabanlı bir API, bir ağaç yapısının etrafında merkezlenir ve bu nedenle, bir ağacın (DOM belgesi olan) Belge arabirimi, Düğüm arabirimi, DüğümList arabirimi, Öğe arabirimi, Attr arabirimi ve benzeri gibi arabirimler sağlar. Ancak, aksine, olay tabanlı bir API işleyicilere arabirimler sağlar. Dört işleyici arabirimi, ContentHandler arabirimi, DTDHandler arabirimi, EntityResolver arabirimi ve ErrorHandler arabirimi vardır.

DOM Ayrıştırıcı ve SAX Ayrıştırıcı arasındaki fark nedir?

DOM ayrıştırıcıları ve SAX ayrıştırıcıları farklı şekillerde çalışır:

  • DOM ayrıştırıcısı giriş belgesinden bellekte bir ağaç yapısı oluşturur ve daha sonra istemciden gelen istekleri bekler. Ancak SAX ayrıştırıcısı herhangi bir iç yapı oluşturmaz. Bunun yerine, bir giriş belgesinin bileşenlerinin olaylarını olay olarak alır ve istemciye girdi belgesi boyunca okurken ne okuduğunu söyler. bir

  • DOM ayrıştırıcısı, istemci tarafından ne kadar gerekli olursa olsun, istemci uygulamasına her zaman tüm belgeyi sunar. Ancak bir SAX ayrıştırıcısı istemci uygulamasına her zaman yalnızca belgenin parçalarıyla birlikte herhangi bir zamanda hizmet eder.

  • DOM ayrıştırıcısı ile, istemci uygulamasındaki yöntem çağrıları açık olmalı ve bir tür zincir oluşturmalıdır. Ancak SAX ile, bazı belirli yöntemler (genellikle cilan tarafından geçersiz kılınır), bazı olaylar gerçekleştiğinde "geri arama" adı verilen bir şekilde otomatik olarak (örtük olarak) çağrılır. Bu yöntemlerin istemci tarafından açıkça çağrılması gerekmez, ancak bunları açıkça çağırabiliriz.

Hangi ayrıştırıcının iyi olduğuna nasıl karar veririz?

İdeal olarak iyi bir ayrıştırıcı hızlı (zaman açısından verimli), alan açısından verimli, işlevsel açıdan zengin ve kullanımı kolay olmalıdır. Ancak gerçekte, ana ayrıştırıcıların hiçbiri aynı anda tüm bu özelliklere sahip değildir. Örneğin, bir DOM Ayrıştırıcı işlevsellik açısından zengindir (çünkü bellekte bir DOM ağacı oluşturur ve belgenin herhangi bir bölümüne art arda erişmenize izin verir ve DOM ağacını değiştirmenize izin verir), ancak belge çok büyük olduğunda alan verimsizdir ve bununla nasıl çalışılacağını öğrenmek biraz zaman alır. Bununla birlikte, bir SAX Parser büyük girdi belgesi durumunda çok daha fazla yer tasarrufu sağlar (çünkü iç yapı oluşturmaz). Dahası, API'si gerçekten basit olduğu için DOM Parser'dan daha hızlı çalışır ve öğrenmesi daha kolaydır. Ancak işlevsellik açısından, daha az fonksiyon sağlar, bu da kullanıcıların kendi veri yapılarını oluşturmak gibi daha fazla özen göstermeleri gerektiği anlamına gelir. Bu arada, iyi bir ayrıştırıcı nedir? Cevabın gerçekten uygulamanızın özelliklerine bağlı olduğunu düşünüyorum.

SAX ayrıştırıcı kullanmanın DOM ayrıştırıcı kullanmanın avantajlı olduğu gerçek dünya uygulamaları nelerdir? Bir DOM ayrıştırıcısı ve bir SAX ayrıştırıcısı için genel uygulama nedir?

Aşağıdaki durumlarda, SAX ayrıştırıcısını kullanmak DOM ayrıştırıcısını kullanmaktan daha avantajlıdır.

  • Giriş belgesi kullanılabilir bellek için çok büyük (aslında bu durumda SAX tek seçeneğinizdir)
  • Belgeyi küçük bitişik girdi yığınlarında işleyebilirsiniz. Yararlı işler yapmadan önce belgenin tamamına ihtiyacınız yoktur
  • Ayrıştırıcıyı yalnızca ilgili bilgileri elde etmek için kullanmak istiyorsunuz ve tüm hesaplamanız tamamen sizin tarafınızdan oluşturulan veri yapılarına dayanacaktır. Aslında uygulamalarımızın çoğunda, genellikle DOM ağacı kadar karmaşık olmayan kendi veri yapılarımızı yaratırız. Bu anlamda, bir DOM ayrıştırıcısı kullanma şansının SAX ayrıştırıcısı kullanma şansından daha az olduğunu düşünüyorum.

Aşağıdaki durumlarda, DOM ayrıştırıcısını kullanmak SAX ayrıştırıcısını kullanmaktan daha avantajlıdır.

  • Başvurunuzun aynı anda belgenin ayrı ayrı bölümlerine erişmesi gerekir.
  • Uygulamanız muhtemelen belgenin kendisi kadar karmaşık olan bir iç veri yapısı kullanabilir.
  • Başvurunuz belgeyi tekrar tekrar değiştirmelidir.
  • Uygulamanız, birçok yöntem çağrısı aracılığıyla belgeyi önemli bir süre boyunca saklamalıdır.

Örnek (DOM ayrıştırıcısı mı yoksa SAX ayrıştırıcısı mı kullanıyorsunuz?):

Bir eğitmenin, öğrencilerin tüm kişisel bilgilerini ve öğrencilerin sınıfında kazandığı noktaları içeren bir XML belgesine sahip olduğunu ve şimdi bir uygulama kullanan öğrenciler için final notları atadığını varsayın. Üretmek istediği şey, SSN ve notların bir listesidir. Ayrıca uygulamasında öğretim elemanının öğrencinin kişisel bilgilerini ve puanlarını saklamak için diziler gibi bir veri yapısı kullanmadığını varsayıyoruz. Eğitmen A'yı sınıf ortalamasını veya daha fazlasını kazananlara A vermeye ve B'leri diğerlerine vermeye karar verirse, başvurusunda bir DOM ayrıştırıcısı kullanması daha iyi olur. Bunun nedeni, belgenin tamamı işlenmeden önce sınıf ortalamasının ne kadar olduğunu bilmesinin hiçbir yolu olmamasıdır. Muhtemelen başvurusunda yapması gereken şey, önce tüm öğrencilerin ve ortalamayı hesaplayın, ardından belgeyi tekrar gözden geçirin ve kazandığı puanları sınıf ortalamasıyla karşılaştırarak her öğrenciye final notu verin. Bununla birlikte, eğitmen öyle bir notlandırma politikası benimserse, 90 puan veya daha fazla olan öğrencilere A ve diğerlerine B atanırsa, muhtemelen bir SAX ayrıştırıcısı kullanması daha iyi olur. Bunun nedeni, her öğrenciye bir final notu atamak için tüm belgenin işlenmesini beklemesine gerek yoktur. SAX ayrıştırıcısı bu öğrencinin notunu okuduğunda hemen bir öğrenciye not verebilir. Yukarıdaki analizde, eğitmenin kendi veri yapısını oluşturmadığını varsaydık. Ya SSN'yi depolamak için bir dizi dizisi ve noktaları saklamak için bir tamsayı dizisi gibi kendi veri yapısını yaratırsa? Bu durumda, Sanırım SAX daha iyi bir seçim, bu da hem hafızadan hem de zamandan tasarruf etmeden önce işi bitirmeden önce. Peki, bu örnek üzerinde bir kez daha düşünülmelidir. Eğitmenin yapmak istediği şey bir liste yazdırmak değil, orijinal dokümanı güncellenen her öğrencinin notuyla geri kaydetmekse ne olur? Bu durumda, bir DOM ayrıştırıcısı hangi derecelendirme politikasını benimsiyor olursa olsun daha iyi bir seçim olmalıdır. Kendi başına herhangi bir veri yapısı oluşturmasına gerek yoktur. Yapması gereken önce DOM ağacını değiştirmek (yani değeri 'sınıf' düğümüne ayarlamak) ve daha sonra değiştirilmiş ağacın tamamını kaydetmektir. Bir DOM ayrıştırıcı yerine SAX ayrıştırıcı kullanmayı seçerse, bu durumda işi yapmadan önce neredeyse bir DOM ağacı kadar karmaşık bir veri yapısı yaratması gerekir. ama işi hallet. Peki, bu örnek üzerinde bir kez daha düşünülmelidir. Eğitmenin yapmak istediği şey bir liste yazdırmak değil, orijinal dokümanı güncellenen her öğrencinin notuyla geri kaydetmekse ne olur? Bu durumda, bir DOM ayrıştırıcısı hangi derecelendirme politikasını benimsiyor olursa olsun daha iyi bir seçim olmalıdır. Kendi başına herhangi bir veri yapısı oluşturmasına gerek yoktur. Yapması gereken önce DOM ağacını değiştirmek (yani değeri 'sınıf' düğümüne ayarlamak) ve daha sonra değiştirilmiş ağacın tamamını kaydetmektir. Bir DOM ayrıştırıcı yerine SAX ayrıştırıcı kullanmayı seçerse, bu durumda işi yapmadan önce neredeyse bir DOM ağacı kadar karmaşık bir veri yapısı yaratması gerekir. ama işi hallet. Peki, bu örnek üzerinde bir kez daha düşünülmelidir. Eğitmenin yapmak istediği şey bir liste yazdırmak değil, orijinal dokümanı güncellenen her öğrencinin notuyla geri kaydetmekse ne olur? Bu durumda, bir DOM ayrıştırıcısı hangi derecelendirme politikasını benimsiyor olursa olsun daha iyi bir seçim olmalıdır. Kendi başına herhangi bir veri yapısı oluşturmasına gerek yoktur. Yapması gereken önce DOM ağacını değiştirmek (yani değeri 'sınıf' düğümüne ayarlamak) ve daha sonra değiştirilmiş ağacın tamamını kaydetmektir. Bir DOM ayrıştırıcı yerine SAX ayrıştırıcı kullanmayı seçerse, bu durumda işi yapmadan önce neredeyse bir DOM ağacı kadar karmaşık bir veri yapısı yaratması gerekir. ama her öğrencinin notu güncellenerek orijinal belgeyi geri kaydetmek için? Bu durumda, bir DOM ayrıştırıcısı hangi derecelendirme politikasını benimsiyor olursa olsun daha iyi bir seçim olmalıdır. Kendi başına herhangi bir veri yapısı oluşturmasına gerek yoktur. Yapması gereken önce DOM ağacını değiştirmek (yani değeri 'sınıf' düğümüne ayarlamak) ve daha sonra değiştirilmiş ağacın tamamını kaydetmektir. Bir DOM ayrıştırıcı yerine SAX ayrıştırıcı kullanmayı seçerse, bu durumda işi yapmadan önce neredeyse bir DOM ağacı kadar karmaşık bir veri yapısı yaratması gerekir. ama her öğrencinin notu güncellenerek orijinal belgeyi geri kaydetmek için? Bu durumda, bir DOM ayrıştırıcısı hangi derecelendirme politikasını benimsiyor olursa olsun daha iyi bir seçim olmalıdır. Kendi veri yapısını oluşturmasına gerek yoktur. Yapması gereken önce DOM ağacını değiştirmek (yani değeri 'sınıf' düğümüne ayarlamak) ve daha sonra değiştirilmiş ağacın tamamını kaydetmektir. Bir DOM ayrıştırıcı yerine SAX ayrıştırıcı kullanmayı seçerse, bu durumda işi yapmadan önce neredeyse bir DOM ağacı kadar karmaşık bir veri yapısı yaratması gerekir. düğümü) ve ardından değiştirilmiş ağacın tamamını kaydedin. Bir DOM ayrıştırıcı yerine SAX ayrıştırıcı kullanmayı seçerse, bu durumda işi yapmadan önce neredeyse bir DOM ağacı kadar karmaşık bir veri yapısı yaratması gerekir. düğümü) ve ardından değiştirilmiş ağacın tamamını kaydedin. Bir DOM ayrıştırıcı yerine SAX ayrıştırıcı kullanmayı seçerse, bu durumda işi yapmadan önce neredeyse bir DOM ağacı kadar karmaşık bir veri yapısı yaratması gerekir.

Bir örnek

Sorun bildirimi : Belirli bir XML belgesindeki öğeler olan çevreler hakkındaki tüm bilgileri ayıklamak için bir Java programı yazın. Her daire öğesinin bir renk özelliğinin yanı sıra üç alt öğeye (yani, x, y ve yarıçap) sahip olduğunu varsayıyoruz. Örnek bir doküman aşağıda verilmiştir:

<?xml version="1.0"?> 
<!DOCTYPE shapes [
<!ELEMENT shapes (circle)*>
<!ELEMENT circle (x,y,radius)>
<!ELEMENT x (#PCDATA)>
<!ELEMENT y (#PCDATA)>
<!ELEMENT radius (#PCDATA)>
<!ATTLIST circle color CDATA #IMPLIED>
]>

<shapes> 
          <circle color="BLUE"> 
                <x>20</x>
                <y>20</y>
                <radius>20</radius> 
          </circle>
          <circle color="RED" >
                <x>40</x>
                <y>40</y>
                <radius>20</radius> 
          </circle>
</shapes> 

DOMparser ile Program

import java.io.*;
import org.w3c.dom.*;
import org.apache.xerces.parsers.DOMParser;


public class shapes_DOM {
   static int numberOfCircles = 0;   // total number of circles seen
   static int x[] = new int[1000];   // X-coordinates of the centers
   static int y[] = new int[1000];   // Y-coordinates of the centers  
   static int r[] = new int[1000];   // radius of the circle
   static String color[] = new String[1000];  // colors of the circles 

   public static void main(String[] args) {   

      try{
         // create a DOMParser
         DOMParser parser=new DOMParser();
         parser.parse(args[0]);

         // get the DOM Document object
         Document doc=parser.getDocument();

         // get all the circle nodes
         NodeList nodelist = doc.getElementsByTagName("circle");
         numberOfCircles =  nodelist.getLength();

         // retrieve all info about the circles
         for(int i=0; i<nodelist.getLength(); i++) {

            // get one circle node
            Node node = nodelist.item(i);

            // get the color attribute 
            NamedNodeMap attrs = node.getAttributes();
            if(attrs.getLength() > 0)
               color[i]=(String)attrs.getNamedItem("color").getNodeValue();

            // get the child nodes of a circle node 
            NodeList childnodelist = node.getChildNodes();

            // get the x and y value 
            for(int j=0; j<childnodelist.getLength(); j++) {
               Node childnode = childnodelist.item(j);
               Node textnode = childnode.getFirstChild();//the only text node
               String childnodename=childnode.getNodeName(); 
               if(childnodename.equals("x")) 
                  x[i]= Integer.parseInt(textnode.getNodeValue().trim());
               else if(childnodename.equals("y")) 
                  y[i]= Integer.parseInt(textnode.getNodeValue().trim());
               else if(childnodename.equals("radius")) 
                  r[i]= Integer.parseInt(textnode.getNodeValue().trim());
            }

         }

         // print the result
         System.out.println("circles="+numberOfCircles);
         for(int i=0;i<numberOfCircles;i++) {
             String line="";
             line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")";
             System.out.println(line);
         }

      }  catch (Exception e) {e.printStackTrace(System.err);}

    }

}

SAXparser ile Program

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.xerces.parsers.SAXParser;


public class shapes_SAX extends DefaultHandler {

   static int numberOfCircles = 0;   // total number of circles seen
   static int x[] = new int[1000];   // X-coordinates of the centers
   static int y[] = new int[1000];   // Y-coordinates of the centers
   static int r[] = new int[1000];   // radius of the circle
   static String color[] = new String[1000];  // colors of the circles

   static int flagX=0;    //to remember what element has occurred
   static int flagY=0;    //to remember what element has occurred
   static int flagR=0;    //to remember what element has occurred

   // main method 
   public static void main(String[] args) {   
      try{
         shapes_SAX SAXHandler = new shapes_SAX (); // an instance of this class
         SAXParser parser=new SAXParser();          // create a SAXParser object 
         parser.setContentHandler(SAXHandler);      // register with the ContentHandler 
         parser.parse(args[0]);
      }  catch (Exception e) {e.printStackTrace(System.err);}  // catch exeptions
   }

   // override the startElement() method
   public void startElement(String uri, String localName, 
                       String rawName, Attributes attributes) {
         if(rawName.equals("circle"))                      // if a circle element is seen
            color[numberOfCircles]=attributes.getValue("color");  // get the color attribute 

         else if(rawName.equals("x"))      // if a x element is seen set the flag as 1 
            flagX=1;
         else if(rawName.equals("y"))      // if a y element is seen set the flag as 2
            flagY=1;
         else if(rawName.equals("radius")) // if a radius element is seen set the flag as 3 
            flagR=1;
   }

   // override the endElement() method
   public void endElement(String uri, String localName, String rawName) {
         // in this example we do not need to do anything else here
         if(rawName.equals("circle"))                       // if a circle element is ended 
            numberOfCircles +=  1;                          // increment the counter 
   }

   // override the characters() method
   public void characters(char characters[], int start, int length) {
         String characterData = 
             (new String(characters,start,length)).trim(); // get the text

         if(flagX==1) {        // indicate this text is for <x> element 
             x[numberOfCircles] = Integer.parseInt(characterData);
             flagX=0;
         }
         else if(flagY==1) {  // indicate this text is for <y> element 
             y[numberOfCircles] = Integer.parseInt(characterData);
             flagY=0;
         }
         else if(flagR==1) {  // indicate this text is for <radius> element 
             r[numberOfCircles] = Integer.parseInt(characterData);
             flagR=0;
         }
   }

   // override the endDocument() method
   public void endDocument() {
         // when the end of document is seen, just print the circle info 
         System.out.println("circles="+numberOfCircles);
         for(int i=0;i<numberOfCircles;i++) {
             String line="";
             line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")";
             System.out.println(line);
         }
   }


}

6

Pratikte: book.xml

<bookstore>
  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
</bookstore>
  • DOM, xml belgesini bellekte aşağıdaki ağaç yapısı olarak sunar.
  • DOM, W3C standardıdır.
  • DOM ayrıştırıcısı Belge Nesne Modeli üzerinde çalışır.
  • DOM, küçük XML belgeleri için daha fazla bellek kaplar
  • DOM'da ileri veya geri gezinmek kolaydır.

resim açıklamasını buraya girin


  • SAX olarak xml belgesini sunar tabanlı olayı gibi start element:abc, end element:abc.
  • SAX, W3C standardı değildir, bir grup geliştirici tarafından geliştirilmiştir.
  • SAX, büyük XML belgeleri için tercih edilen belleği kullanmaz.
  • Belgeleri sırayla işlediğinden geriye doğru gezinme mümkün değildir.
  • Olay bir düğüme / elemana olur ve tüm alt düğümleri (Latin nodüsü, 'düğüm') verir.

Bu XML belgesi, bir SAX ayrıştırıcısından geçirildiğinde, aşağıdaki gibi bir dizi olay oluşturur :

start element: bookstore
start element: book with an attribute category equal to cooking
start element: title with an attribute lang equal to en
Text node, with data equal to Everyday Italian
....
end element: title
.....
end element: book
end element: bookstore

DOM ayrıştırmasının görsel sunumunda neden attr: "lang"yukarıda element: <title>? Bir benzeri XML baktığımızda, görünüşe attronun paralel olmalıdır <element>gibi <book>ve category. Bu sadece yer kazandıran bir teknik mi yoksa amaçlanan bir ebeveyn-çocuk ilişkisi var mı?
1252748

sadece yer kazandıran bir teknik
Premraj

3

DOM Belge Nesne Modelini temsil eder ve her bir öğenin ağaç dallarını temsil ettiği bir XML Belgesini ağaç biçiminde temsil eder. DOM Ayrıştırıcı XML dosyasının bir Bellek İçi ağaç temsilini oluşturur ve daha sonra ayrıştırır, bu nedenle Java.lang.OutOfMemoryError: java yığın alanını önlemek için daha fazla bellek ve DOM ayrıştırıcısı için yığın boyutunun artırılması önerilir. XML dosyası küçükse XML dosyasını ayrıştırmak oldukça hızlıdır, ancak DOM ayrıştırıcısını kullanarak büyük bir XML dosyasını okumaya çalışırsanız, uzun zaman alacağı veya hatta tamamen yükleyemeyeceği için daha fazla olasılık vardır. XML Dom Ağacı oluşturmak için çok fazla bellek gerektirir. Java, DOM Ayrıştırma desteği sağlar ve DOM ayrıştırıcısını kullanarak XML dosyalarını Java'da ayrıştırabilirsiniz. DOM sınıfları w3c.dom paketindeyken, DOM için Parser for Java JAXP (XML Ayrıştırma için Java API) paketindedir.

Java'da SAX XML Ayrıştırıcı

SAX, XML Ayrıştırma için Basit API anlamına gelir. Bu, olay tabanlı bir XML Ayrıştırmadır ve büyük XML Dosyaları için çok uygun XML dosyasını adım adım ayrıştırır. SAX XML Ayrıştırıcısı, açılış etiketi, öğe veya öznitelikle karşılaştığında olayı tetikler ve ayrıştırma buna göre çalışır. Java'da büyük xml dosyalarını ayrıştırmak için SAX XML ayrıştırıcısının kullanılması önerilir, çünkü tüm XML dosyasını Java'ya yüklemesi gerekmez ve küçük parçalar halinde büyük bir XML dosyasını okuyabilir. Java SAX ayrıştırıcı için destek sağlar ve SAX Parser kullanarak Java herhangi bir xml dosyasını ayrıştırabilirsiniz, ben burada SAX Parser kullanarak xml dosyası okuma örneği ele aldım. Java'da SAX Parser kullanmanın bir dezavantajı, SAX Parser kullanarak Java'da XML dosyasının okunmasının DOM Parser ile karşılaştırıldığında daha fazla kod gerektirmesidir.

DOM ve SAX XML Ayrıştırıcısı arasındaki fark

Java'da DOM ayrıştırıcısı ile SAX Ayrıştırıcısı arasında birkaç üst düzey fark vardır:

1) DOM ayrıştırıcısı tüm xml belgesini belleğe yüklerken, SAX XML dosyasının yalnızca küçük bir bölümünü belleğe yükler.

2) DOM ayrıştırıcısı bellekteki tüm XML belgesine eriştiği için SAX'tan daha hızlıdır.

3) Java'daki SAX ayrıştırıcısı, çok fazla bellek gerektirmediğinden, büyük XML dosyası için DOM Ayrıştırıcıdan daha uygundur.

4) DOM ayrıştırıcısı Belge Nesne Modeli üzerinde çalışırken SAX olay tabanlı bir xml ayrıştırıcısıdır.

Daha fazla bilgi için: http://javarevisited.blogspot.com/2011/12/difference-between-dom-and-sax-parsers.html#ixzz2uz1bJQqZ


2

Hem SAX hem de DOM, XML belgesini ayrıştırmak için kullanılır. Her ikisinin de avantajları ve dezavantajları vardır ve duruma bağlı olarak programlamamızda kullanılabilir

SAX:

  1. Düğümü düğüme göre ayrıştırır

  2. XML'i bellekte saklamaz

  3. Düğüm ekleyemiyor veya silemiyoruz

  4. Yukarıdan aşağıya geçiş

DOM

  1. İşleme başlamadan önce tüm XML belgesini belleğe kaydeder

  2. Daha fazla bellek kaplar

  3. Düğüm ekleyebilir veya silebiliriz

  4. Herhangi bir yönde hareket edin.

Bir düğüm bulmamız gerekiyorsa ve eklememiz veya silmemiz gerekmiyorsa, SAX'in kendisiyle gidebiliriz, aksi takdirde daha fazla belleğimiz varsa DOM.


1

1) DOM ayrıştırıcısı tüm XML belgesini belleğe yüklerken, SAX XML dosyasının yalnızca küçük bir bölümünü belleğe yükler.

2) DOM ayrıştırıcısı bellekteki tüm XML belgesine eriştiği için SAX'tan daha hızlıdır.

3) Java'daki SAX ayrıştırıcısı, çok fazla bellek gerektirmediğinden, büyük XML dosyası için DOM Ayrıştırıcıdan daha uygundur.

4) DOM ayrıştırıcı Belge Nesne Modeli üzerinde çalışırken SAX olay tabanlı bir XML ayrıştırıcıdır.

Daha fazla bilgi için: http://javarevisited.blogspot.com/2011/12/difference-between-dom-and-sax-parsers.html#ixzz498y3vPFR

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.