Welchen XML-Parser soll ich in C ++ verwenden? [geschlossen]

344

Ich habe XML-Dokumente, die ich analysieren und / oder XML-Dokumente erstellen und in Text (entweder Dateien oder Speicher) schreiben muss. Was soll ich verwenden, da die C ++ - Standardbibliothek keine Bibliothek dafür hat?

Hinweis: Dies soll eine endgültige Frage im C ++ - FAQ-Stil sein. Also ja, es ist ein Duplikat von anderen. Ich habe mir diese anderen Fragen nicht einfach angeeignet, weil sie eher nach etwas Spezifischerem fragten. Diese Frage ist allgemeiner.

Nicol Bolas
quelle
Ich mag tiCpp code.google.com/p/ticpp , die Dokumente sind (noch?) Nicht großartig, aber ich liebe die Bibliothek, schönen, sauberen Code.
Ich schrieb mein eigenes github.com/igagis/mikroxml
igagis

Antworten:

679

Wie bei Standard-Bibliothekscontainern hängt es von Ihren Anforderungen ab, welche Bibliothek Sie verwenden sollten. Hier ist ein praktisches Flussdiagramm:

Geben Sie hier die Bildbeschreibung ein

Die erste Frage lautet also: Was brauchst du?

Ich benötige vollständige XML-Konformität

OK, Sie müssen also XML verarbeiten. Kein Spielzeug-XML, echtes XML. Sie müssen in der Lage sein, alle XML-Spezifikationen zu lesen und zu schreiben , nicht nur die tief liegenden, leicht zu analysierenden Bits. Sie benötigen Namespaces, DocTypes, Entity-Ersetzung, die Werke. Die W3C-XML-Spezifikation in ihrer Gesamtheit.

Die nächste Frage lautet: Muss Ihre API DOM oder SAX entsprechen?

Ich benötige eine genaue DOM- und / oder SAX-Konformität

OK, die API muss also wirklich DOM und / oder SAX sein. Es kann nicht nur ein Push-Parser im SAX-Stil oder ein beibehaltener Parser im DOM-Stil sein. Es muss das tatsächliche DOM oder das tatsächliche SAX sein, soweit C ++ dies zulässt.

Du hast gewählt:

Xerces

Das ist deine Entscheidung. Es ist so ziemlich der einzige C ++ - XML-Parser / -Schreiber, der die vollständige (oder so nahe wie C ++ zulässt) DOM- und SAX-Konformität aufweist. Es bietet außerdem XInclude-Unterstützung, XML-Schema-Unterstützung und eine Vielzahl weiterer Funktionen.

Es hat keine wirklichen Abhängigkeiten. Es verwendet die Apache-Lizenz.

DOM- und / oder SAX-Konformität sind mir egal

Du hast gewählt:

LibXML2

LibXML2 bietet eine C-artige Oberfläche (wenn Sie das wirklich stört, verwenden Sie Xerces), obwohl die Oberfläche zumindest etwas objektbasiert und einfach zu verpacken ist. Es bietet eine Vielzahl von Funktionen, wie XInclude - Unterstützung (mit Rückrufe so , dass man es kann sagen , wo es die Datei aus bekommt), einen XPath 1.0 Erkenner, RelaxNG und Schematron Unterstützung (obwohl die Fehlermeldungen einen lassen viel zu wünschen übrig), und so weiter.

Es hat zwar eine Abhängigkeit von iconv, kann jedoch ohne diese Abhängigkeit konfiguriert werden. Dies bedeutet jedoch, dass Sie nur eine begrenzte Anzahl möglicher Textcodierungen haben, die analysiert werden können.

Es verwendet die MIT-Lizenz.

Ich benötige keine vollständige XML-Konformität

OK, die vollständige XML-Konformität spielt für Sie keine Rolle. Ihre XML-Dokumente unterliegen entweder vollständig Ihrer Kontrolle oder verwenden garantiert die "grundlegende Teilmenge" von XML: keine Namespaces, Entitäten usw.

Was ist dir wichtig? Die nächste Frage lautet: Was ist für Sie das Wichtigste in Ihrer XML-Arbeit?

Maximale XML-Parsing-Leistung

Ihre Anwendung muss XML verwenden und es so schnell wie möglich in C ++ - Datenstrukturen umwandeln.

Du hast gewählt:

RapidXML

Dieser XML-Parser ist genau das, was er verspricht: Rapid XML. Es geht nicht einmal darum, die Datei in den Speicher zu ziehen. Wie das passiert, liegt bei Ihnen. Dabei wird das in eine Reihe von C ++ - Datenstrukturen analysiert, auf die Sie zugreifen können. Und das ungefähr so ​​schnell, wie es dauert, um die Datei Byte für Byte zu scannen.

Natürlich gibt es kein kostenloses Mittagessen. Wie die meisten XML-Parser, die sich nicht für die XML-Spezifikation interessieren, berührt Rapid XML keine Namespaces, DocTypes, Entitäten (mit Ausnahme von Zeichenentitäten und den 6 grundlegenden XML-Entitäten) usw. Also im Grunde Knoten, Elemente, Attribute und so weiter.

Außerdem ist es ein Parser im DOM-Stil. Es ist also erforderlich, dass Sie den gesamten Text einlesen. Sie kopieren jedoch (normalerweise) keinen dieser Texte. Die Art und Weise RapidXML die meisten seine Geschwindigkeit wird durch Zeichenkette beziehen an Ort und Stelle . Dies erfordert mehr Speicherverwaltung von Ihrer Seite (Sie müssen diese Zeichenfolge am Leben erhalten, während RapidXML sie betrachtet).

Das DOM von RapidXML ist einfach. Sie können Zeichenfolgenwerte für Dinge erhalten. Sie können nach Attributen nach Namen suchen. Das ist alles. Es gibt keine praktischen Funktionen, um Attribute in andere Werte (Zahlen, Datumsangaben usw.) umzuwandeln. Sie bekommen nur Zeichenfolgen.

Ein weiterer Nachteil von RapidXML ist, dass das Schreiben von XML schmerzhaft ist . Es erfordert viel explizite Speicherzuweisung von Zeichenfolgennamen, um das DOM zu erstellen. Es bietet zwar eine Art Zeichenfolgenpuffer, erfordert jedoch noch viel explizite Arbeit. Es ist sicherlich funktionell, aber es ist ein Schmerz zu benutzen.

Es verwendet die MIT-Lizenz. Es ist eine reine Header-Bibliothek ohne Abhängigkeiten.

Leistung ist mir wichtig, aber nicht so sehr

Ja, Leistung ist Ihnen wichtig. Aber vielleicht brauchen Sie etwas weniger nacktes. Vielleicht etwas, das mehr Unicode verarbeiten kann oder nicht so viel benutzergesteuertes Speichermanagement erfordert. Leistung ist immer noch wichtig, aber Sie möchten etwas weniger direktes.

Du hast gewählt:

PugiXML

Historisch gesehen diente dies als Inspiration für RapidXML. Die beiden Projekte sind jedoch unterschiedlich, da Pugi mehr Funktionen bietet, während RapidXML sich ausschließlich auf die Geschwindigkeit konzentriert.

PugiXML bietet Unterstützung für die Unicode-Konvertierung. Wenn Sie also einige UTF-16-Dokumente haben und diese als UTF-8 lesen möchten, wird Pugi diese bereitstellen. Es hat sogar eine XPath 1.0-Implementierung, wenn Sie so etwas brauchen.

Aber Pugi ist immer noch ziemlich schnell. Wie RapidXML hat es keine Abhängigkeiten und wird unter der MIT-Lizenz vertrieben.

Riesige Dokumente lesen

Sie müssen Dokumente lesen, deren Größe in Gigabyte gemessen wird . Vielleicht bekommen Sie sie von stdin und werden von einem anderen Prozess gefüttert. Oder Sie lesen sie aus riesigen Dateien. Oder Wasauchimmer. Der Punkt ist, dass Sie nicht die gesamte Datei auf einmal in den Speicher lesen müssen, um sie zu verarbeiten.

Du hast gewählt:

LibXML2

Die SAX-API von Xerces funktioniert in dieser Funktion, aber LibXML2 ist hier, weil es etwas einfacher ist, damit zu arbeiten. Eine API im SAX-Stil ist eine Push-API: Sie beginnt mit dem Parsen eines Streams und löst nur Ereignisse aus, die Sie abfangen müssen. Sie sind gezwungen, Kontext, Status usw. zu verwalten. Code, der eine SAX-ähnliche API liest, ist viel weiter verbreitet, als man hoffen könnte.

Das xmlReaderObjekt von LibXML2 ist eine Pull-API. Sie fragen nach dem nächsten XML - Knoten oder Elemente zu gehen; es wird dir nicht gesagt. Auf diese Weise können Sie den Kontext nach Belieben speichern und verschiedene Entitäten auf eine Weise behandeln, die im Code viel besser lesbar ist als eine Reihe von Rückrufen.

Alternativen

Expat

Expat ist ein bekannter C ++ - Parser, der eine Pull-Parser-API verwendet. Es wurde von James Clark geschrieben.

Der aktuelle Status ist aktiv. Die neueste Version ist 2.2.9, die am (25.09.2019) veröffentlicht wurde.

LlamaXML

Es ist eine Implementierung einer StAX-API. Es ist ein Pull-Parser, ähnlich dem xmlReaderParser von LibXML2 .

Aber es wurde seit 2005 nicht mehr aktualisiert. Also noch einmal, Caveat Emptor.

XPath-Unterstützung

XPath ist ein System zum Abfragen von Elementen in einem XML-Baum. Dies ist eine praktische Möglichkeit, ein Element oder eine Sammlung von Elementen mithilfe einer standardisierten Syntax effektiv nach allgemeinen Eigenschaften zu benennen. Viele XML-Bibliotheken bieten XPath-Unterstützung.

Hier gibt es effektiv drei Möglichkeiten:

  • LibXML2 : Es bietet volle XPath 1.0-Unterstützung. Auch hier handelt es sich um eine C-API. Wenn Sie dies stört, gibt es Alternativen.
  • PugiXML : Es wird auch XPath 1.0 unterstützt. Wie oben ist es eher eine C ++ - API als LibXML2, sodass Sie sich damit möglicherweise besser auskennen.
  • TinyXML : XPath wird nicht unterstützt, aber es gibt die TinyXPath- Bibliothek, die es bereitstellt. TinyXML wird derzeit auf Version 2.0 konvertiert, wodurch sich die API erheblich ändert, sodass TinyXPath möglicherweise nicht mit der neuen API funktioniert. Wie TinyXML selbst wird TinyXPath unter der zLib-Lizenz vertrieben.

Erledige einfach den Job

Die XML-Korrektheit ist Ihnen also egal. Leistung ist für Sie kein Problem. Streaming ist irrelevant. Alles, was Sie wollen, ist etwas , das XML in den Speicher bringt und es Ihnen ermöglicht, es wieder auf die Festplatte zu kleben. Was Sie interessiert, ist API.

Sie möchten einen XML-Parser, der klein, einfach zu installieren, trivial zu verwenden und klein genug ist, um für die Größe Ihrer eventuellen ausführbaren Datei irrelevant zu sein.

Du hast gewählt:

TinyXML

Ich habe TinyXML in diesen Slot eingefügt, weil es ungefähr so ​​einfach zu bedienen ist wie XML-Parser. Ja, es ist langsam, aber es ist einfach und offensichtlich. Es hat viele praktische Funktionen zum Konvertieren von Attributen und so weiter.

Das Schreiben von XML ist in TinyXML kein Problem. Sie stellen einfach neweinige Objekte zusammen, hängen sie zusammen, senden das Dokument an a std::ostream, und alle sind glücklich.

Es gibt auch so etwas wie ein Ökosystem, das auf TinyXML basiert, mit einer iteratorfreundlicheren API und sogar einer darauf geschichteten XPath 1.0-Implementierung.

TinyXML verwendet die zLib-Lizenz, bei der es sich mehr oder weniger um die MIT-Lizenz mit einem anderen Namen handelt.

Nicol Bolas
quelle
6
Das sieht ein bisschen wie ein Copy-Paste aus. Können Sie das Quelldokument verknüpfen?
Joel
28
@Joel: Sehr oft, wenn jemand seine eigene Frage mit einem guten langen Beitrag beantwortet, liegt dies daran, dass er im Geiste von Jeffs Rat folgt - insbesondere, weil eine so lala Frage oft geschlossen werden kann, bevor eine gute Antwort möglich ist gebucht werden, wenn die Person die Antwort genau dann und dort schreibt. Indem Sie sich etwas Zeit nehmen, um eine Antwort vorzubereiten, bevor er die Frage stellt :) Nicol bietet uns allen einen hervorragenden Kandidaten für Close-> Duplicate-Fragen in der Zukunft.
Sarnold
28
@ Joel: Ich fürchte, ich kann nicht. Es war nur ein temporäres Dokument, aus dem ich in Notepad ++ kopiert habe. Ich habe es nie gespeichert, daher kann ich dich nicht damit verknüpfen;)
Nicol Bolas
6
Erwähnenswert ist möglicherweise die neuere Version von TinyXML: TinyXML-2 verwendet eine ähnliche API wie TinyXML-1 und dieselben umfangreichen Testfälle. Die Implementierung des Parsers wurde jedoch komplett neu geschrieben, um ihn für die Verwendung in einem Spiel besser geeignet zu machen. Es benötigt weniger Speicher, ist schneller und benötigt nur sehr wenige Speicherzuordnungen.
Johnbakers
6
Ich mag diese Frage und Antwort, finde sie aber auch Unix-voreingenommen. Keine Erwähnung von MSXML und XmlLite? Wenn die Multi-Paltform-Portabilität Ihr Grund ist, diese auszuschließen, sollte dies in der Frage und Antwort klar erwähnt werden. (Andernfalls könnten einige Leute zB Libxml2 für ein Windows-Projekt auswählen, das nach Kopfschmerzen fragt, die leicht hätten vermieden werden können.)
Scrontch
17

Es gibt einen anderen Ansatz für den Umgang mit XML, den Sie möglicherweise in Betracht ziehen möchten: die XML-Datenbindung. Insbesondere, wenn Sie bereits eine formale Spezifikation Ihres XML-Vokabulars haben, z. B. im XML-Schema.

Mit der XML-Datenbindung können Sie XML verwenden, ohne XML-Analyse oder -Serialisierung durchzuführen. Ein Datenbindungs-Compiler generiert automatisch den gesamten Code auf niedriger Ebene und präsentiert die analysierten Daten als C ++ - Klassen, die Ihrer Anwendungsdomäne entsprechen. Sie arbeiten dann mit diesen Daten, indem Sie Funktionen aufrufen und mit C ++ - Typen (int, double usw.) arbeiten, anstatt Zeichenfolgen zu vergleichen und Text zu analysieren (was Sie mit XML-Zugriffs-APIs auf niedriger Ebene wie DOM oder SAX tun).

Siehe zum Beispiel eine von mir geschriebene Open-Source-Implementierung für die XML-Datenbindung, CodeSynthesis XSD, und für eine leichtere, abhängigkeitsfreie Version CodeSynthesis XSD / e .

Boris Kolpackov
quelle
13
Ich habe nichts gegen den Beitrag, aber die SO-Richtlinie besagt, dass Sie, wenn Sie etwas vorschlagen, das Sie geschrieben haben, erwähnen sollten, dass Sie es geschrieben haben, im Interesse einer vollständigen Offenlegung.
Nicol Bolas
@Nicol Ich habe es in die Antwort bearbeitet.
JBentley
Vielleicht ist diese Liste hilfreich, aber ich konnte nicht herausfinden, wer die Autoren dieser Liste sind (ohne öffentliche Offenlegung kann ich nicht sehen, ob die Beschreibungen und Bewertungen aussagekräftig sind). Vielleicht kann man an den Blick W3C Daten Arbeitsgruppe verbindlich , dass die Listen mehrere Datentools Bindung , die in der Öffentlichkeit und wurden für die Prüfung und Berichterstattung (vollständige Offenlegung verwendet: Ich bin nicht mit dem Unternehmen assoziiert CodeSynthesis, habe ich geholfen gsoap mit dem W3C aufgeführt Werkzeuge).
Dr. Alex RE
1

Ein weiterer Hinweis zu Expat: Es lohnt sich, nach der Arbeit mit eingebetteten Systemen zu suchen. Die Dokumentation, die Sie wahrscheinlich im Internet finden, ist jedoch uralt und falsch. Der Quellcode enthält tatsächlich ziemlich gründliche Kommentare auf Funktionsebene, aber es wird einige Zeit dauern, bis sie sinnvoll sind.

Haltepunkt
quelle
0

OK dann. Ich habe eine neue erstellt, da keine der Listen meinen Anforderungen entsprach.

Leistungen:

  1. Pull-Parser-Streaming-API auf niedriger Ebene ( Java StAX-ähnlich )
  2. Ausnahmen und RTTI-Modi werden unterstützt
  3. Begrenzung der Speichernutzung, Unterstützung für große Dateien (getestet mit 100 mib XMark-Datei von, Geschwindigkeit hängt von der Hardware ab)
  4. UNICODE-Unterstützung und automatische Erkennung für die Eingabequellencodierung
  5. High-Level-API zum Einlesen in Strukturen / POCO
  6. Meta-Programmier-API zum Schreiben und Generieren von XSD aus Strukturen / POCO mit Unterstützung für XML-Strukturen (Attribute und Verschachtelungs-Tags) (XSD-Generierung benötigt RTTI, kann jedoch nur beim Debuggen verwendet werden, um es einmal zu erstellen)
  7. C ++ 11 - GCC und VC ++ 15+

Nachteile:

  1. DTD- und XSD-Validierung noch nicht bereitgestellt
  2. Das Abrufen von XML / XSD über HTTP / HTTPS ist noch nicht abgeschlossen
  3. Neue Bibliothek

Projekt nach Hause

Victor Gubin
quelle
1
Könnten Sie Benchmarks hinzufügen?
Vadim Peretokin
-1

In Secured Globe , Inc. verwenden wir rapidxml . Wir haben alle anderen ausprobiert, aber rapidxml scheint die beste Wahl für uns zu sein.

Hier ist ein Beispiel:

 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);
Michael Haephrati
quelle