wake-up-neo.com

Welchen XML-Parser sollte ich in C++ verwenden?

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

Hinweis: Dies ist als endgültige Frage im C++ - FAQ-Stil gedacht. Ja, es ist ein Duplikat von anderen. Ich habe diese anderen Fragen nicht einfach angesprochen, weil sie dazu neigten, etwas genauer zu fragen. Diese Frage ist allgemeiner.

307
Nicol Bolas

Wie bei Standard-Bibliothekscontainern hängt die zu verwendende Bibliothek von Ihren Anforderungen ab. Hier ist ein praktisches Flussdiagramm:

enter image description here

Die erste Frage lautet also: Was brauchst du?

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

OK, also müssen Sie XML verarbeiten. Nicht Spielzeug XML, real XML. Sie müssen in der Lage sein, alle der XML-Spezifikation zu lesen und zu schreiben, nicht nur die niedrig liegenden, leicht zu analysierenden Bits. Sie benötigen Namespaces, DocTypes, Entity-Substitution, die funktioniert. Die W3C XML-Spezifikation in ihrer Gesamtheit.

Die nächste Frage lautet: Muss Ihre API DOM- oder SAX-konform sein?

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 ist muss das tatsächliche DOM oder das tatsächliche SAX, soweit C++ dies zulässt.

Du hast gewählt:

Xerces

Das ist deine Entscheidung. Es ist so ziemlich der einzige C++ - XML-Parser/Writer, der vollständige (oder so nahe wie C++) DOM- und SAX-Konformität aufweist. Es bietet auch XInclude-Unterstützung, XML-Schema-Unterstützung und eine Vielzahl anderer Funktionen.

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

DOM- und/oder SAX-Konformität interessieren mich nicht

Du hast gewählt:

LibXML2

LibXML2 bietet eine Schnittstelle im C-Stil (wenn Sie das wirklich stört, verwenden Sie Xerces), obwohl die Schnittstelle zumindest einigermaßen objektbasiert und einfach zu verpacken ist. Es bietet viele Funktionen, wie XInclude-Unterstützung (mit Rückrufen, damit Sie feststellen können, woher die Datei stammt), XPath 1.0-Erkennung, RelaxNG- und Schematron-Unterstützung (obwohl die Fehlermeldungen ein lot hinterlassen = zu wünschen übrig) und so weiter.

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

Es wird die Lizenz MIT verwendet.

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 es wird garantiert, dass Sie die "grundlegende Teilmenge" von XML verwenden: keine Namespaces, Entitäten usw.

Also, was ist für dich wichtig? Die nächste Frage lautet: Was ist Ihnen bei Ihrer XML-Arbeit am wichtigsten?

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 es verspricht: Rapid XML. Es geht nicht einmal darum, die Datei in den Speicher zu ziehen. Wie das passiert, liegt bei Ihnen. Es analysiert dies in eine Reihe von C++ - Datenstrukturen, 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 mit der XML-Spezifikation befassen, berührt Rapid XML keine Namespaces, DocTypes, Entities (mit Ausnahme von Zeichen-Entities und den 6 grundlegenden XML-Entities) und so weiter. 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. Was es jedoch nicht tut, ist copy (in der Regel) jeder dieser Texte. Die Art und Weise, in der RapidXML den größten Teil seiner Geschwindigkeit erzielt, ist die Bezugnahme auf Zeichenfolgen in-place. Dies erfordert mehr Speicherverwaltung von Ihrer Seite (Sie müssen diese Zeichenfolge am Leben erhalten, während RapidXML sie überprüft).

Das DOM von RapidXML ist ein absolutes Muss. Sie können Zeichenfolgenwerte für Dinge abrufen. Sie können anhand des Namens nach Attributen suchen. Das ist alles. Es gibt keine praktischen Funktionen, um Attribute in andere Werte (Zahlen, Daten usw.) umzuwandeln. Sie bekommen nur Saiten.

Ein weiterer Nachteil von RapidXML ist, dass es schmerzhaft für writing XML ist. Es erfordert viel explizite Speicherzuweisung von Zeichenfolgennamen, um das DOM zu erstellen. Es stellt zwar eine Art Zeichenfolgenpuffer bereit, dies erfordert jedoch noch viel explizite Arbeit. Es funktioniert auf jeden Fall, aber es ist ein Schmerz, es zu benutzen.

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

Ich interessiere mich für Leistung, 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 direkt.

Du hast gewählt:

PugiXML

In der Vergangenheit 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 über UTF-16-Dokumente verfügen und diese als UTF-8 lesen möchten, bietet Pugi diese an. 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 Lizenz MIT vertrieben.

Riesige Dokumente lesen

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

Du hast gewählt:

LibXML2

Die SAX-ähnliche API von Xerces wird in dieser Funktion funktionieren, aber LibXML2 ist hier, weil es ein bisschen einfacher ist, damit zu arbeiten. Eine SAX-API ist eine Push-API: Sie beginnt mit der Analyse eines Streams und löst nur Ereignisse aus, die Sie abfangen müssen. Sie sind gezwungen, den Kontext, den Zustand usw. zu verwalten. Code, der eine SAX-ähnliche API liest, ist weitaus weiter verbreitet, als man vielleicht erhofft.

Das xmlReader -Objekt von LibXML2 ist eine Pull-API. Sie fragen, um zum nächsten XML-Knoten oder -Element zu wechseln. es wird dir nicht gesagt Auf diese Weise können Sie den Kontext nach Belieben speichern und verschiedene Entitäten so behandeln, dass sie im Code besser lesbar sind 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.5, die letzten Monat (31.10.2017) veröffentlicht wurde.

LlamaXML

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

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

XPath-Unterstützung

XPath ist ein System zum Abfragen von Elementen in einem XML-Baum. Mit dieser praktischen Methode können Sie ein Element oder eine Auflistung von Elementen anhand allgemeiner Eigenschaften effektiv benennen, indem Sie eine standardisierte Syntax verwenden. Viele XML-Bibliotheken bieten XPath-Unterstützung.

Hier gibt es effektiv drei Möglichkeiten:

  • LibXML2 : Es bietet vollständige XPath 1.0-Unterstützung. Auch hier handelt es sich um eine C-API. Wenn Sie also gestört werden, gibt es Alternativen.
  • PugiXML : Auch XPath 1.0 wird unterstützt. Wie oben ist es eher eine C++ - API als LibXML2, so dass Sie sich vielleicht besser damit auskennen.
  • TinyXML : Es kommt nicht mit XPath-Unterstützung, aber es gibt die TinyXPath Bibliothek, die es zur Verfügung stellt. TinyXML wird auf Version 2.0 konvertiert, wodurch die API erheblich geändert wird, sodass TinyXPath möglicherweise nicht mit der neuen API funktioniert. Wie TinyXML selbst wird TinyXPath unter der zLib-Lizenz vertrieben.

Erledige einfach den Job

Sie kümmern sich also nicht um die XML-Korrektheit. Leistung ist für Sie kein Problem. Streaming ist irrelevant. Alles, was Sie wollen, ist etwas, das XML in den Speicher holt und es Ihnen ermöglicht, es wieder auf die Festplatte zu kopieren. Was Sie interessiert, ist API.

Sie möchten einen XML-Parser, der klein, einfach zu installieren, einfach zu verwenden und klein genug ist, um für die Größe Ihrer späteren ausführbaren Datei keine Rolle zu spielen.

Du hast gewählt:

TinyXML

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

Das Schreiben von XML ist in TinyXML kein Problem. Sie new nur einige Objekte, befestigen Sie sie zusammen, senden Sie das Dokument an einen std::ostream, und jeder ist glücklich.

Es gibt auch ein Ökosystem, das um TinyXML herum aufgebaut ist, mit einer iteratorfreundlicheren API und sogar einer darüber geschichteten XPath 1.0-Implementierung.

TinyXML verwendet die zLib-Lizenz, die mehr oder weniger die MIT-Lizenz mit einem anderen Namen ist.

634
Nicol Bolas

Es gibt einen anderen Ansatz zum Umgang mit XML, den Sie berücksichtigen möchten, die XMLdata-Bindung. Insbesondere wenn Sie bereits eine formale Spezifikation Ihres XML-Vokabulars haben, zum Beispiel in XML Schema. 

Durch die XML-Datenbindung können Sie XML verwenden, ohne XML-Analyse oder -Serialisierung durchzuführen. Ein Datenbindungscompiler generiert automatisch den gesamten untergeordneten Code und stellt die geparsten Daten als C++ - Klassen dar, 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 (wie Sie es mit Low-Level-XML-Zugriffs-APIs wie DOM oder SAX tun).

Siehe zum Beispiel eine Open-Source-XML-Datenbindungsimplementierung, die ich geschrieben habe, CodeSynthesis XSD und, für eine Version mit geringerem Gewicht und Abhängigkeit, CodeSynthesis XSD /. e .

17
Boris Kolpackov

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);
0

Noch eine Anmerkung zu Expat: Es lohnt sich, nach eingebetteten Systemen zu suchen. Die Dokumentation, die Sie wahrscheinlich im Internet finden, ist uralt und falsch. Der Quellcode hat eigentlich ziemlich gründliche Kommentare auf Funktionsebene, aber es braucht einige Durchsichten, um sie zu verstehen.

0
breakpoint
0
Michael

OK dann. Ich habe eine neue erstellt, da keine der Listen meine Bedürfnisse nicht erfüllt. 

Leistungen:

  1. Pull-Parser-Streaming-API auf niedriger Ebene ( Java StAX wie )
  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 from, Geschwindigkeit hängt von der Hardware ab)
  4. UNICODE-Unterstützung und automatische Erkennung der Eingabequellencodierung 
  5. API auf hoher Ebene zum Einlesen in Strukturen/POCO
  6. Meta-Programmier-API zum Schreiben und Generieren von XSD aus structures/POCO Mit Unterstützung für XML-Struktur (Attribute und Verschachtelungs-Tags) (XSD-Generierung benötigt RTTI, kann jedoch nur beim Debuggen verwendet werden, um es einmalig zu machen)
  7. C++ 11 - GCC und VC++ 15+

Nachteile:

  1. DTD- und XSD-Validierung noch nicht bereitgestellt 
  2. XML/XSD per HTTP/HTTPS abrufen, noch nicht abgeschlossen
  3. Neue Bibliothek

Projekt nach Hause

0
Victor Gubin