webentwicklung-frage-antwort-db.com.de

Verwenden von Boost zum Lesen und Schreiben von XML-Dateien

Gibt es eine gute Möglichkeit (und auch eine einfache Möglichkeit), mit Boost XML-Dateien zu lesen und zu schreiben?

Ich kann anscheinend kein einfaches Beispiel zum Lesen von XML-Dateien mit Boost finden. Können Sie mir ein einfaches Beispiel zeigen, in dem Boost zum Lesen und Schreiben von XML-Dateien verwendet wird?

Wenn nicht Boost, gibt es eine gute und einfache Bibliothek zum Lesen und Schreiben von XML-Dateien, die Sie empfehlen können? (es muss eine C++ Bibliothek sein)

68
Nuno

Sie sollten versuchen pugixml Leichter, einfacher und schneller XML-Parser für C++

Das Schönste an pugixml ist die XPath Unterstützung, die TinyXML und RapidXML fehlt.

Zitat des RapidXML-Autors "Ich möchte Arseny Kapoulkine für seine Arbeit an Pugixml danken, die eine Inspiration für dieses Projekt war" und "5 bis 30% schneller als Pugixml, der schnellste mir bekannte XML-Parser". Er hatte gegen Version 0.3 getestet von Pugixml, die vor kurzem Version 0.42 erreicht hat.

Hier ist ein Auszug aus der pugixml-Dokumentation:

Die Hauptmerkmale sind:

  • geringer Speicherverbrauch und Fragmentierung (der Gewinn über Pugxml beträgt das 1,3-fache, TinyXML das 2,5-fache, Xerces (DOM) das 4,3-fache 1). Genaue Zahlen können im Abschnitt Vergleich mit vorhandenen Parsern eingesehen werden.
  • extrem hohe Parsing - Geschwindigkeit (der Gewinn über Pugxml ist ~ 6 - mal, TinyXML - ~ 10 - mal, Xerces - DOM - ~ 17,6 - mal 1
  • extrem hohe Parsing-Geschwindigkeit (nun, ich wiederhole mich selbst, aber es ist so schnell, dass es Expat in Test-XML um das 2,8-fache übertrifft) 2
  • mehr oder weniger standardkonform (mit Ausnahme von DTD-bezogenen Problemen werden alle standardkonformen Dateien korrekt analysiert)
  • ziemlich fehlerfrei (es verschluckt sich nicht an etwas wie You & Me, wie Expat; es analysiert Dateien mit Daten in falscher Codierung; und so weiter)
  • saubere Oberfläche (eine stark überarbeitete Pugxml-Oberfläche)
  • mehr oder weniger Unicode-fähig (tatsächlich wird die UTF-8-Codierung der Eingabedaten vorausgesetzt, obwohl dies problemlos mit ANSI funktioniert - derzeit noch kein UTF-16 (siehe Zukünftige Arbeit), mit Hilfskonvertierungsfunktionen (UTF-8 <- > UTF-16/32 (was auch immer der Standard für std :: wstring & wchar_t ist))
  • vollständig standardkonformer C++ - Code (von Comeau im strengen Modus genehmigt); Die Bibliothek ist plattformübergreifend (Plattformliste siehe Referenz).
  • hohe Flexibilität. Sie können viele Aspekte des Datei-Parsings und des DOM-Baumaufbaus über Parsing-Optionen steuern.

Okay, könnten Sie fragen - was ist der Haken? Alles ist so süß - es ist eine kleine, schnelle, robuste und saubere Lösung zum Parsen von XML. Was fehlt? Ok, wir sind faire Entwickler - hier ist eine Liste mit Fehlfunktionen:

  • speicherverbrauch. Es schlägt jeden DOM-basierten Parser, den ich kenne - aber wenn der SAX-Parser kommt, gibt es keine Chance. Sie können keine 2-GB-XML-Datei mit weniger als 4 GB Arbeitsspeicher verarbeiten - und das schnell. Obwohl sich pugixml besser verhält als alle anderen DOM-basierten Parser, ist dies kein Problem, wenn Sie mit DOM nicht weiterkommen.
  • speicherverbrauch. Ok, ich wiederhole mich. Nochmal. Wenn Sie mit anderen Parsern XML-Dateien in einem konstanten Speicher (oder sogar als Speicherbereich) bereitstellen können, ist dies mit pugixml nicht möglich. Sie müssen also die gesamten Daten in einen nicht konstanten Speicher kopieren. Darüber hinaus sollte es während der Lebensdauer des Parsers bestehen bleiben (die Gründe dafür und mehr über die Lebensdauer werden weiter unten beschrieben). Wenn Sie mit DOM einverstanden sind, sollte dies kein Problem sein, da der Gesamtspeicherverbrauch geringer ist (obwohl Sie einen zusammenhängenden Teil des Speichers benötigen, der ein Problem sein kann).
  • mangel an Validierung, DTD-Verarbeitung, XML-Namespaces, ordnungsgemäße Behandlung der Codierung. Wenn Sie diese benötigen, nehmen Sie MSXML oder XercesC oder ähnliches.
63
Cristian Adam

TinyXML ist wahrscheinlich eine gute Wahl. Was Boost angeht:

Es gibt die Property_Tree Bibliothek im Boost Repository . Es wurde akzeptiert, aber momentan scheint die Unterstützung zu fehlen (EDIT: Property_Tree ist jetzt Teil von Boost seit Version 1.41 , lies die Dokumentation = in Bezug auf seine XML-Funktionalität).

Daniel Nuffer hat einen xml-Parser für Boost Spirit implementiert.

23
stephan

Es gibt auch TinyXML , eine nette und kleine C++ Bibliothek. Wenn Sie nach einer Bibliothek auf niedrigerer Ebene suchen, ist RapidXML ein guter Ausgangspunkt.

16
Anteru

Boost verwendet RapidXML wie in - beschrieben Kapitel XML-Parser der Seite So füllen Sie einen Eigenschaftsbaum aus :

Leider gibt es zum Zeitpunkt des Schreibens keinen XML Parser in Boost . Die Bibliothek enthält daher den Parser fast and tiny RapidXML (derzeit in Version 1.13), um XML-Parsing zu unterstützen. RapidXML unterstützt den XML-Standard nicht vollständig. Es ist nicht in der Lage, DTDs zu analysieren, und kann daher keine vollständige Entitätsersetzung durchführen.

Bitte beachten Sie auch das XML-Boost-Tutorial .

Da das OP eine "einfache Möglichkeit zum Verwenden von Boost zum Lesen und Schreiben von XML-Dateien" möchte, führe ich nachfolgend ein sehr einfaches Beispiel an:

<main>
    <owner>Matt</owner>
    <cats>
        <cat>Scarface Max</cat>
        <cat>Moose</cat>
        <cat>Snowball</cat>
        <cat>Powerball</cat>
        <cat>Miss Pudge</cat>
        <cat>Needlenose</cat>
        <cat>Sweety Pie</cat>
        <cat>Peacey</cat>
        <cat>Funnyface</cat>
    </cats>
</main>

(Katzennamen sind von Matt Mahoneys Homepage )

Die entsprechende Struktur in C++:

struct Catowner
{
    std::string           owner;
    std::set<std::string> cats;
};

read_xml() Verwendung:

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

Catowner load(const std::string &file)
{
    boost::property_tree::ptree pt;
    read_xml(file, pt);

    Catowner co;

    co.owner = pt.get<std::string>("main.owner");

    BOOST_FOREACH(
       boost::property_tree::ptree::value_type &v,
       pt.get_child("main.cats"))
       co.cats.insert(v.second.data());

    return co;
}

write_xml() Verwendung:

void save(const Catowner &co, const std::string &file)
{
   boost::property_tree::ptree pt;

   pt.put("main.owner", co.owner);

   BOOST_FOREACH(
      const std::string &name, co.cats)
      pt.add("main.cats.cat", name);

   write_xml(file, pt);
}
10
olibre

Boost bietet keinen XML-Parser atm.

Poco XML (Teil der Poco C++ - Bibliotheken ) ist gut und einfach.

4
StackedCrooked

Nun, es gibt keine spezifische Bibliothek in Boost für XML-Parsing, aber es gibt viele Alternativen, hier ein paar: libxml , Xerces , Expat

Natürlich können Sie einige der anderen Bibliotheken in Boost verwenden, um Ihre eigene Bibliothek zu erstellen, aber das wird wahrscheinlich ein ziemliches Unterfangen sein.

Und hier ist ein ganzer Artikel zum Thema von IBM.

4
Skurmedel

Es scheint, dass Boost-Serialisierung in XML aus Archiven lesen und in sie schreiben kann, wenn dies für Ihre Zwecke ausreicht.

Einfacheres XML mit Boost

4
Stuart

Verwenden Sie auf jeden Fall TinyXML * Daumen hoch *

3
StfnoPad

Wenn Sie nur nach DOM-Funktionen suchen, enthält dieser Thread bereits einige Vorschläge. Ich persönlich würde mich wahrscheinlich nicht mit einer Bibliothek ohne XPath-Unterstützung herumschlagen und in C++ Qt verwenden. Es gibt auch TinyXPath und Arabica behauptet, XPath-Unterstützung zu haben, aber dazu kann ich überhaupt nichts sagen.

2
Vladimir Prus

Schauen Sie sich Arabica an

2

Aus meinen Erfahrungen in der Boost-Mailingliste geht hervor, dass jedes Mal, wenn XML als Betreff angezeigt wird, eine Diskussion über Unicode stattfindet. Da sich derzeit jedoch eine potenzielle Unicode-Bibliothek abzeichnet, wird es meiner Meinung nach nicht allzu lange dauern, bis eine XML-Bibliothek dort angezeigt wird.

In der Zwischenzeit habe auch ich TinyXML verwendet.

Interessanter Link zu RapidXML. Ich werde mir das mal ansehen.

1
Kaz Dragon

Es gibt einen GSoC-Vorschlag zur Verbesserung des bestehenden Vorschlags von Boost.XML: https://github.com/stefanseefeld/boost.xml , aber wie Andrzej vorgeschlagen hat, ist Boost.PropertyTree für diese Aufgabe nett. Abhängig natürlich von der XML-Größe und der benötigten Validierungsunterstützung.

Es gibt auch eine Bibliothek, die kürzlich auf der Boost-Mailingliste vorgeschlagen wurde: http://www.codesynthesis.com/projects/libstudxml/doc/intro.xhtml

1
daminetreg

Eine Warnung. Ich liebe RapidXML, aber es hat einen sehr bösen Fehler beim Parsen von UTF16. Einige gültige Werte führen zum Absturz.

Ich würde gerne pugixml empfehlen - aber es fehlt die Namespace-Unterstützung, von der ich weiß, dass sie mir Probleme bereiten wird.

1

Was ist mit boost.spirit?

hier , sie zeigen einen " Mini XML " Parser

0
tagoma
<?xml version="1.0"?>
<Settings>
  <GroupA>
      <One>4</One>
      <Two>7</Two>
      <Three>9</Three> 
  </GroupA>
  <GroupA>
      <One>454</One>
      <Two>47</Two>
      <Three>29</Three> 
  </GroupA>
  <GroupB>
      <A>String A</A>
      <B>String B</B>  
  </GroupB>  
</Settings>

Es gibt eine einfache Möglichkeit, XML mit BOOST zu lesen. Dieses Beispiel basiert auf std :: wstring:

#include <string> 
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/foreach.hpp>

bool CMyClass::ReadXML(std::wstring &full_path)
{
    using boost::property_tree::wptree;

    // Populate tree structure pt:
    wptree pt;
    std::wstringstream ss; ss << load_text_file(full_path); // See below for ref.
    read_xml(ss, pt);

    // Traverse pt:
    BOOST_FOREACH(wptree::value_type const& v, pt.get_child(L"Settings"))
    {
        if (v.first == L"GroupA")
        {
            unsigned int n1 = v.second.get<unsigned int>(L"One");
            unsigned int n2 = v.second.get<unsigned int>(L"Two");
            unsigned int n3= v.second.get<unsigned int>(L"Three");
        }
        else if (v.first == L"GroupB")
        {
            std::wstring wstrA = v.second.get<std::wstring>(L"A");
            std::wstring wstrB = v.second.get<std::wstring>(L"B");
        }
    };
}

Attribute zu lesen ist nur ein bisschen komplizierter.

-

Nur als referenz:

std::wstring load_text_file(std::wstring &full_path)
{
    std::wifstream wif(full_path);

    wif.seekg(0, std::ios::end);
    buffer.resize(wif.tellg());
    wif.seekg(0);
    wif.read(buffer.data(), buffer.size());

    return buffer;
}
0
Amit G.