C ++ 'da hangi XML ayrıştırıcısını kullanmalıyım? [kapalı]


344

Ayrıştırma gereken XML belgeleri var ve / veya XML belgeleri oluşturmak ve bunları metin (dosya veya bellek) yazmak gerekiyor. C ++ standart kitaplığında bunun için bir kitaplık olmadığından ne kullanmalıyım?

Not: Bunun kesin, C ++ - SSS tarzı bir soru olması amaçlanmıştır. Yani evet, başkalarının kopyası. Bu diğer soruları uygun bulmadım çünkü biraz daha spesifik bir şey isteme eğilimindeydiler. Bu soru daha genel.


TiCpp code.google.com/p/ticpp'i seviyorum , dokümanlar harika değil (henüz?), Ancak kütüphaneyi seviyorum, güzel temiz kod.

Yanıtlar:


679

Standart kütüphane kaplarında olduğu gibi, hangi kütüphaneyi kullanmanız gerektiğine bağlıdır. İşte uygun bir akış şeması:

resim açıklamasını buraya girin

İlk soru şudur: Neye ihtiyacınız var?

Tam XML Uyumluluğuna İhtiyacım Var

Tamam, bu yüzden XML'i işlemeniz gerekir. Oyuncak XML değil, gerçek XML. Yalnızca alçakta olan, ayrıştırması kolay bitleri değil, tüm XML özelliklerini de okuyabilmeniz ve yazabilmeniz gerekir . Ad Alanları, DocTypes, varlık ikamesi, işlere ihtiyacınız var. W3C XML Spesifikasyonu, bütünüyle.

Sonraki soru: API'nızın DOM veya SAX ile uyumlu olması gerekiyor mu?

Tam DOM ve / veya SAX Uyumluluğuna İhtiyacım Var

Tamam, bu yüzden DOM ve / veya SAX için gerçekten API'ye ihtiyacınız var. Sadece SAX tarzı bir itici ayrıştırıcı veya bir DOM tarzı tutulan ayrıştırıcı olamaz. Bu gereken C ++ izin verdiği ölçüde gerçek DOM veya gerçek SAX olmak.

Siz seçtiniz:

Xerces

Bu senin seçimin. DOM ve SAX uyumluluğu tam olan (veya C ++ 'ın izin verdiği kadar yakın) tek C ++ XML ayrıştırıcı / yazar. Ayrıca XInclude desteği, XML Şeması desteği ve diğer birçok özelliğe de sahiptir.

Gerçek bir bağımlılığı yoktur. Apache lisansını kullanır.

DOM ve / veya SAX Uyumluluğunu Önemiyorum

Siz seçtiniz:

libxml2

LibXML2, C-tarzı bir arayüz sunar (eğer gerçekten rahatsız ederseniz, Xerces'i kullanın), ancak arayüz en azından biraz nesne tabanlı ve kolayca sarılır. XInclude desteği (dosyayı nereden aldığını söyleyebilmeniz için geri çağrıları olan), XPath 1.0 tanıyıcı, RelaxNG ve Schematron desteği (hata mesajları arzulanan bir çok şey bıraksa da) gibi birçok özellik sağlar ve böylece.

İconv'ye bağımlılığı vardır, ancak bu bağımlılık olmadan yapılandırılabilir. Her ne kadar bu, ayrıştırabileceği daha sınırlı sayıda olası metin kodlamasına sahip olacağınız anlamına gelir.

MIT lisansını kullanır.

Tam XML Uyumluluğuna İhtiyacım Yok

Tamam, tam XML uyumluluğu sizin için önemli değil. XML belgeleriniz tamamen sizin kontrolünüz altındadır veya XML'in "temel alt kümesini" kullanması garanti edilir: ad alanı, varlık vb. Yok.

Peki senin için ne önemli? Bir sonraki soru: XML çalışmanızda sizin için en önemli şey nedir?

Maksimum XML Ayrıştırma Performansı

Uygulamanızın XML alması ve bu dönüşüm gerçekleşebileceği kadar hızlı bir şekilde C ++ veri yapılarına dönüştürmesi gerekir.

Siz seçtiniz:

RapidXML

Bu XML ayrıştırıcısı tam olarak kalayda yazdığı şeydir: hızlı XML. Dosyayı belleğe çekmekle bile ilgilenmiyor; bunun nasıl olduğu size kalmış. Bununla ilgilenen, erişebileceğiniz bir dizi C ++ veri yapısına ayrıştırmaktır. Ve bunu dosya bayt bayt taramak için gereken kadar hızlı yapar.

Tabii ki, ücretsiz öğle yemeği diye bir şey yoktur. XML spesifikasyonunu umursamayan çoğu XML ayrıştırıcısı gibi Hızlı XML de ad alanlarına, DocTypes'e, varlıklara (karakter varlıkları ve 6 temel XML olanlar hariç) dokunmaz. Temel olarak düğümler, elemanlar, nitelikler ve benzeri.

Ayrıca, DOM tarzı bir ayrıştırıcıdır. Bu nedenle, içindeki tüm metni okumanızı gerektirir. Ancak, yapmadığı şey o metnin herhangi birini (genellikle) kopyalamaktır . RapidXML'nin hızının çoğunu alma yolu, dizeleri yerinde ifade etmektir . Bu sizin tarafınızdan daha fazla bellek yönetimi gerektirir (RapidXML ona bakarken bu dizeyi canlı tutmalısınız).

RapidXML'nin DOM'si çıplak kemiktir. Şeyler için dize değerleri alabilirsiniz. Nitelikleri ada göre arayabilirsiniz. Bu kadar. Nitelikleri diğer değerlere (sayılar, tarihler, vb.) Dönüştürmek için kolaylık işlevi yoktur. Sadece ipler alıyorsun.

RapidXML ile diğer bir dezavantaj, XML yazmak için acı verici olmasıdır . DOM'sini oluşturmak için dize adlarının çok fazla açık bellek ayırmasını yapmanızı gerektirir. Bir tür dize arabelleği sağlar, ancak yine de sonunuzda çok fazla açık çalışma gerektirir. Kesinlikle işlevsel, ancak kullanmak için bir acı.

MIT lisansını kullanır. Bağımlılığı olmayan, yalnızca başlık içeren bir kitaplıktır.

Performansı önemsiyorum ama o kadar da değil

Evet, performans sizin için önemlidir. Ama belki biraz daha az çıplak kemiklere ihtiyacınız var. Belki daha fazla Unicode işleyebilen veya çok fazla kullanıcı tarafından kontrol edilen bellek yönetimi gerektirmeyen bir şey. Performans hala önemlidir, ancak biraz daha az doğrudan bir şey istersiniz.

Siz seçtiniz:

PugiXML

Tarihsel olarak, bu RapidXML için ilham kaynağı oldu. Ancak iki proje ayrıldı, Pugi daha fazla özellik sunarken, RapidXML tamamen hıza odaklandı.

PugiXML, Unicode dönüştürme desteği sunar, bu nedenle etrafında bazı UTF-16 dokümanlarınız varsa ve bunları UTF-8 olarak okumak istiyorsanız, Pugi sağlayacaktır. Bu tür bir şeye ihtiyacınız varsa, XPath 1.0 uygulaması bile vardır.

Ancak Pugi hala oldukça hızlı. RapidXML gibi, bağımlılığı yoktur ve MIT Lisansı altında dağıtılır.

Büyük Belgeleri Okuma

Boyut olarak gigabayt cinsinden ölçülen belgeleri okumalısınız . Belki onları stdin'den alıyorsunuz, başka bir süreçle besleniyorsunuz. Ya da onları büyük dosyalardan okuyorsunuz. Ya da her neyse. Mesele şu ki, ihtiyacınız olan şey tüm dosyayı işlemek için bir kerede belleğe okumak zorunda kalmamaktır .

Siz seçtiniz:

libxml2

Xerces'in SAX tarzı API'sı bu kapasitede çalışacak, ancak LibXML2 burada, çünkü çalışmak biraz daha kolay. SAX tarzı API bir push-API'dir: bir akışı ayrıştırmaya başlar ve sadece yakalamanız gereken etkinlikleri tetikler. Bağlamı, durumu vb. Yönetmek zorundasınız. SAX tarzı bir API okuyan kod, umduğundan çok daha fazla yayılmıştır.

LibXML2'nin xmlReadernesnesi bir çekme API'sidir . Sen sor sonraki XML düğümü veya eleman gitmek için; size söylenmedi. Bu, bağlamı uygun gördüğünüz şekilde depolamanıza, farklı varlıkları kodda bir grup geri çağrıdan çok daha okunabilir bir şekilde işlemenize olanak tanır.

Alternatifler

Gurbetçi

Expat, pull-parser API kullanan iyi bilinen bir C ++ ayrıştırıcısıdır. James Clark tarafından yazılmıştır.

Mevcut durumu aktif. En son sürüm 2.2.9 sürümüdür (2019-09-25).

LlamaXML

StAX tarzı bir API uygulamasıdır. LibXML2'nin xmlReaderayrıştırıcısına benzeyen bir çekme ayrıştırıcısıdır.

Ama 2005'ten beri güncellenmedi. Yine, Caveat Emptor.

XPath Desteği

XPath, bir XML ağacındaki öğeleri sorgulamak için bir sistemdir. Standart bir sözdizimi kullanarak bir öğeyi veya öğe koleksiyonunu ortak özelliklere göre etkili bir şekilde adlandırmanın kullanışlı bir yoludur. Birçok XML kitaplığı XPath desteği sunar.

Burada etkili bir şekilde üç seçenek vardır:

  • LibXML2 : Tam XPath 1.0 desteği sağlar. Yine, bir C API'sı, bu yüzden sizi rahatsız ederse, alternatifler var.
  • PugiXML : XPath 1.0 desteği ile birlikte geliyor. Yukarıdaki gibi, LibXML2'den daha çok bir C ++ API'sıdır, bu yüzden onunla daha rahat olabilirsiniz.
  • TinyXML : XPath desteği ile birlikte gelmez, ancak bunu sağlayan TinyXPath kütüphanesi vardır. TinyXML, API'yı önemli ölçüde değiştiren sürüm 2.0'a dönüştürülüyor, bu nedenle TinyXPath yeni API ile çalışmayabilir. TinyXML'nin kendisi gibi, TinyXPath zLib lisansı altında dağıtılır.

Sadece İşi Tamamlayın

Bu nedenle, XML doğruluğunu umursamazsınız. Performans sizin için sorun değil. Akış önemsizdir. Tek istediğin olan şey belleğe XML alır ve bir daha geri diske üzerine sopa sağlar. Ne sen bakım yaklaşık API'sıdır.

Küçük, kurulumu kolay, kullanımı önemsiz ve nihai yürütülebilir dosyanızın boyutu ile alakasız olacak bir XML ayrıştırıcısı istiyorsunuz.

Siz seçtiniz:

TinyXML

TinyXML'yi bu yuvaya koydum çünkü XML ayrıştırıcılarının aldığı gibi kullanımı kolay bir braindead kadar basit. Evet, yavaş, ama basit ve açık. Öznitelikleri dönüştürmek için birçok kolaylık fonksiyonuna sahiptir.

TinyXML'de XML yazmak sorun değil. Sadece newbazı nesneler kadar, bunları birbirine tutturmak bir belgeyi göndermek std::ostreamve herkesin mutlu.

Ayrıca, daha yineleyici dostu bir API ile TinyXML etrafında inşa edilmiş bir ekosistem ve hatta bunun üzerine katmanlı bir XPath 1.0 uygulaması da var.

TinyXML, aşağı yukarı farklı bir ada sahip MIT Lisansı olan zLib lisansını kullanır.


6
Bu biraz kopyala-yapıştır gibi görünüyor. Kaynak belgeyi bağlayabilir misiniz?
Joel

28
@Joel: Birisi kendi sorusunu iyi bir uzun mesajla cevapladığında, Jeff'in tavsiyesi ruhu içinde takip ettikleri için - özellikle de böyle bir soruya benzeyen şey genellikle iyi bir cevap vermeden önce kapatılabileceğinden kişi cevap o zaman ve orada yazıyorsa. O soruyu :) Nicol bize sağlayan sormadan önce bir yanıt hazırlamak için biraz zaman alarak tüm gelecekte KAPATMA-> Yinelenen sorular için mükemmel bir aday ile.
sarnold

28
@Joel: Korkarım yapamam. Notepad ++ ile kopyaladığım geçici bir belgedir. Ben hiç kurtarmadım, bu yüzden seni ona bağlayamıyorum;)
Nicol Bolas

6
TinyXML'in daha yeni bir versiyonundan bahsetmeye değer olabilir: TinyXML-2, TinyXML-1 ve benzer zengin test senaryolarına benzer bir API kullanır. Ancak ayrıştırıcının uygulanması, bir oyunda kullanılmasını daha uygun hale getirmek için tamamen yeniden yazılmıştır. Daha az bellek kullanır, daha hızlıdır ve çok az bellek ayırma kullanır.
johnbakers

6
Bu soruyu ve cevabı beğendim, ama bunu da Unix önyargılı buluyorum. MSXML ve XmlLite'den bahsedilmiyor mu? Çoklu paltform taşınabilirlik, bunları hariç tutma nedeninizse, bu soru ve cevapta açıkça belirtilmelidir. (Aksi takdirde, bazı insanlar sadece Windows için bir proje için Libxml2'yi seçebilir ve bu da kolayca önlenebilecek baş ağrıları ister.)
13'te Scrontch

17

XML'i işlemek için XML veri bağlama adı verilen başka bir yaklaşım daha vardır. Özellikle XML kelime dağarcığınızın, örneğin XML Şeması'nda, resmi bir belirtiminiz varsa.

XML veri bağlama, herhangi bir XML ayrıştırma veya serileştirme yapmadan XML kullanmanızı sağlar. Veri bağlama derleyicisi, tüm düşük düzeyli kodu otomatik olarak oluşturur ve ayrıştırılan verileri uygulama etki alanınıza karşılık gelen C ++ sınıfları olarak sunar. Daha sonra, işlevleri çağırarak ve dizeleri karşılaştırmak ve metni ayrıştırmak yerine (DOM veya SAX gibi düşük düzeyli XML erişim API'leriyle yaptığınız şey) C ++ türleriyle (int, double vb.) Çalışarak bu verilerle çalışırsınız.

Örneğin, yazdığım açık kaynaklı bir XML veri bağlama uygulamasına bakın, CodeSynthesis XSD ve daha hafif bir bağımlılık içermeyen sürüm için CodeSynthesis XSD / e .


13
Gönderiyi umursamıyorum, ancak SO politikası, yazdığınız bir şeyi önerirseniz, tam açıklama amacıyla yazdığınızı belirtmeniz gerektiğini belirtir.
Nicol Bolas

@Nicol Cevabı düzenledim.
JBentley

Belki de bu liste yararlıdır, ancak bu listenin yazar (lar) ının kim olduğunu bulamadım (kamuya açıklama olmadan açıklamaların ve derecelendirmelerin anlamlı olup olmadığını göremiyorum). Belki de kamusal alanda olan ve test ve raporlama için kullanılan çeşitli veri bağlama araçlarını listeleyen W3C veri bağlama çalışma grubuna bakabiliriz (tam açıklama: CodeSynthesis ile ilişkili değilim, W3C'de listelenen gsoap'a yardımcı oldum araçlar).
RE

1

Expat ile ilgili bir not daha: gömülü sistemlerin çalışmasına bakmaya değer. Ancak, web'de bulacağınız belgeler eski ve yanlıştır. Kaynak kodu aslında oldukça kapsamlı fonksiyon seviyesi yorumlarına sahiptir, ancak mantıklı olmaları için biraz fazla zaman alacaktır.



0

Tamam ozaman. Listenin hiçbiri ihtiyaçlarımı karşılamadığı için yeni bir tane oluşturdum.

Yararları:

  1. Düşük düzeyde Pull-parser Akış API'sı ( Java StAX benzeri )
  2. İstisnalar ve desteklenen RTTI modları
  3. Bellek kullanımı için sınır, büyük dosyalar için destek (100 mib XMark dosyası ile test edildi , hız donanıma bağlıdır)
  4. UNICODE desteği ve giriş kaynağı kodlaması için otomatik algılama
  5. Yapılara okuma için yüksek seviye API / POCO
  6. Yapılardan XSD yazmak ve üretmek için meta-programlama API'sı / POCO xml yapısı (özellikler ve yuvalama etiketleri) desteği ile (XSD oluşturma RTTI gerektirir, ancak bir kez yapmak için sadece hata ayıklamada kullanılabilir)
  7. C ++ 11 - GCC ve VC ++ 15+

Dezavantajları:

  1. DTD ve XSD doğrulaması henüz sağlanmadı
  2. HTTP / HTTPS ile XML / XSD edinme devam ediyor, henüz yapılmadı
  3. Yeni kütüphane

Proje ana sayfası


1
Kıyaslama ekleyebilir misiniz?
Vadim Peretokin

-1

Gelen Güvenli Globe , Inc. kullandığımız rapidxml . Diğerlerini denedik ama rapidxml bizim için en iyi seçim gibi görünüyor.

İşte bir örnek:

 rapidxml::xml_document<char> doc;
    doc.parse<0>(xmlData);
    rapidxml::xml_node<char>* root = doc.first_node();

    rapidxml::xml_node<char>* node_account = 0;
    if (GetNodeByElementName(root, "Account", &node_account) == true)
    {
        rapidxml::xml_node<char>* node_default = 0;
        if (GetNodeByElementName(node_account, "default", &node_default) == true)
        {
            swprintf(result, 100, L"%hs", node_default->value());
            free(xmlData);
            return true;
        }
    }
    free(xmlData);
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.