xml Datei auslesen ohne externen Parser möglich?



  • Tag

    Es gibt einige Threads zu diesem Thema, aber alle empfehlen einen externen Parser, den man in sein Projekt einfügen soll.
    Hat C++ nicht selber irgend eine Funktion, die es erlaubt, aus einem Textfile oder auch xml-File Tags (<tag>5</tag>) durchzugehen, den Integer auszulesen und diese zusammen zu addieren?
    Mit diesem Code z.B. kann ich ein Wort aus einem Text auslesen; aber würde gern das Wort lesen, es in einem Array oder Stack zu speichern und dann alle Werte im Stack zusammen zu addieren.

    #include <fstream>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
      char str[10];
    
      ifstream b_file ( "example.txt" );
    
      b_file>> str;
    
      cout<< str <<"\n";
    
    }
    

    Ich hoffe die Frage ist nicht zu trivial,

    danke im Voraus.



  • Nein da hat C++ nichts. Also selber schreiben (nur in extrem einfachen Fällen zu empfehlen) oder eine Bibliothek benutzen. Ich benutze z.B. libxml2, es gibt aber mit Sicherheit kleinere/einfachere.
    Oder man setzt direkt eine geeignete Skriptsprache ein, wenn es nicht in ein größeres C++ Projekt integriert werden soll.



  • Kannst dich ja mal an einen Parser mit Boost::Spirit machen 😃



  • Kóyaánasqatsi schrieb:

    Kannst dich ja mal an einen Parser mit Boost::Spirit machen 😃

    Sollte nicht besonders schwer fallen wenn man sich mal ein wenig damit auseinandergesetzt hat 🙂



  • pumuckl schrieb:

    Sollte nicht besonders schwer fallen wenn man sich mal ein wenig damit auseinandergesetzt hat 🙂

    Man kann XML Parsing relativ einfach mit Boost::Regex selber programmieren.
    Noch einfacher, wenn man mit Regex ein custom XML Parsing baut, das nur für seine speziellen XML Dateien benutzt werden soll..

    mfg, René



  • Hallo;
    danke fuer die Antworten; ich habe mir die erwaehnten Parser angeschaut, die bestehen alle aus vielen Klassen und Files; anders gesagt: Ich versteh nur Bahnhof...
    Das xml-File, das ich einlesen muss, ist recht einfach aufgebaut; leider habe ich bisher keine Tutorials finden koennen, die fuer C++ erklaeren, wie man einen Parser schreibt; habt ihr irgendwelche Beispiele oder etwas in der Art? (Nein, ich gehe hier nicht davon aus, dass jemand die Aufgabe fuer mich loest)
    Weil ich nicht weiss, wie ich hier ein File hochladen kann, unten stehend der Inhalt des Files, das geparst werden muss

    <circuit>
    	<series>
    		<resistance>"5"</resistance>
    		<parallel>
    			<resistance>"2"</resistance
    			<series>
    				<resistance>"1"</resistance>
    				<coil>"1"</coil>
    			</series>
    		</parallel>
    		<condenser>"2"</condenser>
    	</series>
    </circuit>
    


  • Ich kann jetzt das ganze File auslesen,
    nun ist das Problem, die einzelnen Tags zu identifizieren und ihren jeweiligen Wert zu speichern

    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        char     filename[128];
        ifstream file;
        char     zeile[1024];
    
        // Dateinamen einlesen
        cout << "Dateinamen eingeben: " << flush;
        cin.getline(filename, 127);
    
        // Datei öffnen
        file.open(filename, ios::in);
    
        if (file.good())
        {
            // Wenn die Datei geoeffnet werden konnte...
    
            // An den Anfang der Datei springen
            file.seekg(0L, ios::beg);
    
            while (! file.eof())
            {
                // Die Datei zeilenweise auslesen
                file.getline(zeile, 1024);
                cout << zeile << endl;
            }
        }
        else
        {
            // Wenn die Datei nicht geoeffnet werden konnte,
            // aus welchen Gruenden auch immer...
            cout << "Datei nicht gefunden." << endl;
        }
    
        return 0;
    }
    


  • file.getline(zeile, 1024);
    

    Wie ekelhaft ist das denn 😮



  • Schoenheit ist unwichtig, es muss funktionieren;
    wenn schon Kritik, dann bitte konstruktive



  • Das war doch Kritik 😃
    Und wenn du so denkst, hast du sowieso schon verloren.



  • Anstatt mit chars zu arbeiten würde ich strings nehmen. Die machen die Sache schonmal einfacher, da du z.B. mit string.substr() den Text zwischen den >< auslesen kannst.

    Allerdings wird so eine Konstruktion schnell ziemlich hässlich und unübersichtlich, weswegen ich doch zu einem richtigen XML-Parser greifen würde (libxml, tinyxml, etc.).

    Boost::Spirit ist wohl auch sehr gut, allerdings habe ich es bis jetzt noch nicht richtig zum laufen bekommen.

    MfG,
    ScRaT



  • Kóyaánasqatsi schrieb:

    Das war doch Kritik 😃
    Und wenn du so denkst, hast du sowieso schon verloren.

    Aber keine konstruktive. Du bist einfach nur ein destruktiver Troll, den keiner leiden kann. Das heißt, du hast verloren und nicht er..

    @OP: Mach das mit boost:regex, geht relativ einfach! Wenn du nicht weißt, wie Reguläre Ausdrücke funktionieren, musst du dich wohl einarbeiten, ist aber eine Sache, wo du extremst froh sein wirst, das zu können.. Braucht man immer mal wieder.

    mfg, René~



  • NewSoftzzz schrieb:

    Aber keine konstruktive. Du bist einfach nur ein destruktiver Troll, den keiner leiden kann. Das heißt, du hast verloren und nicht er..

    Er weiß nun das std::ifstream::getline in dem Fall nicht so gut kommt, also war es konstruktiv. Und wer kann mich nicht leiden?



  • Ich habe jetzt folgenden Code; ich kann die Tags und die Nummern ausfiltern;
    weiss jemand eine Funktion, mit der ich die Zahlen zusammen rechnen kann?

    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <fstream>
    #include <stack>
    
    using namespace std;
    
    string parse_tag (string input)
    {
        string   output;
        bool     tag_opened = false;
        int      j          = 0;
    
        for (int i=0;i<input.length();i++)
        {
           if      (tag_opened == true  && input[i]=='>') return(output);
           else if (                       input[i]=='<') tag_opened = true;
           else if (tag_opened                          ) output += input[i];
        }
        return(output);
    }
    
    string parse_quote (string input)
    {
        string   output;
        bool     quote_opened = false;
        int      j            = 0;
    
        for (int i=0;i<input.length();i++)
        {
           if      (quote_opened == true  && input[i]=='"') return(output);
           else if (                         input[i]=='"') quote_opened = true;
           else if (quote_opened                          ) output += input[i];
        }
        return(output);
    }
    
    int main(int argc, char *argv[])
    {
        char          filename[128];
        ifstream      file;
        string        zeile;
        stack<string> stack;
        string        test ("");
        struct        complex {
            float     real;
            float     imag;
        };
    
       //char zeile[];
    
        // Dateinamen einlesen
    //    cout << "Dateinamen eingeben: ";
    
    //    cin >> filename;
    
        // Datei öffnen
       // file.open(filename, ios::in);
        file.open("inputfile.dat"); //filename);
    
        if (file.good())
        {
            // Wenn die Datei geoeffnet werden konnte...
    
            // An den Anfang der Datei springen
            file.seekg(ios::beg);
    
            while (! file.eof())
            {
                // Die Datei zeilenweise auslesen
                getline(file, zeile);
    //            zeile.replace(zeile.begin(), zeile.end(), ' ');
                test = parse_tag(zeile);
                if (!test.empty()) cout << test << endl;
                test = parse_quote(zeile);
                if (!test.empty()) cout << test << endl;
    //            cout << "zeile" << zeile << endl;
    //cout << endl;
                stack.push (zeile);
    
    /*            while (stack.size()>1)
                {
    
                }
    */        }
        }
        else
        {
            // Wenn die Datei nicht geoeffnet werden konnte
            cout << "Datei nicht gefunden." << endl;
        }
    
        return 0;
    }
    


  • Du wirst auf diese Weise wirklich nichts gescheites auf die Reihe bekommen. Vielleicht wirst du es mit viel Arbeit schaffen, dass es läuft, aber das Teil wird so instabil sein, dass du die darin investierte Zeit schnell bedauern wirst.
    Bei deinem Beispielcode fehlt übrigens ein > das könnte einem mal eben kurz selbstgeschriebenen Parser schnell zum Exitus bringen.



  • Wie kann ich denn den Code verbessern?



  • SSJ schrieb:

    Wie kann ich denn den Code verbessern?

    Benutz RegEx? Aber warum antworte ich überhaupt, wenn du eh nicht auf die Vorschläge eingehst? -.-

    mfg, René~



  • Ich habe erst als ich meinen aktuellen Code gepostet habe, gesehen, dass noch weitere Antworten gab, irgendwie habe ich keine e-mail Benachrichtigung erhalten;
    ich wuerde sehr gerne auf Vorschlaege eingehen, wenn ich sie verstehen wuerde;
    nein, RegEx benutze ich nicht; externe Parser sind nicht erlaubt, muss alles selber schreiben



  • SSJ schrieb:

    nein, RegEx benutze ich nicht; externe Parser sind nicht erlaubt, muss alles selber schreiben

    RegEx ist aber kein Parser, das ist ein normales Werkzeug und seit C++0x sogar im Standard. Dann weißt du ja jetzt, was du tun musst 😉

    mfg, René~



  • Hat C++ nicht selber irgend eine Funktion, die es erlaubt, aus einem Textfile oder auch xml-File Tags (<tag>5</tag>) durchzugehen

    Noch mal auf deinen Ursprungspost einzugehen, genau DAS wäre dann RegEx.

    boost::regex tagz0r("<tag>\\d+</tag>");
    

    Genau für sowas ist es da, nur die Zahl müsstest du noch mit atoi umrechnen und selber addieren.

    PS: Wenn du nicht glaubst, dass RegEx standard ist und damit keine externe Funktion mehr (in C++0x), schaue dort:
    http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n3000.pdf
    Seite 1039.

    mfg, René~


Anmelden zum Antworten