2010-05-11 24 views
16

Muszę parsować plik XML w C++. Szukałem i znalazłem bibliotekę RapidXml do tego.Jak analizować plik XML w RapidXML

Mam wątpliwości dotyczące doc.parse<0>(xml).

Może to być plik .xml lub musi to być string lub char *?

Jeśli mogę wziąć tylko string lub char *, to myślę, że muszę przeczytać cały plik i zapisać go w tablicy znaków i przekazać wskaźnik do funkcji?

Czy istnieje sposób, aby bezpośrednio korzystać z pliku, ponieważ będę musiał również zmienić plik XML wewnątrz kodu.

Jeśli nie jest to możliwe w RapidXML, sugerujemy inne biblioteki XML w C++.

Dzięki!

Ashd

+1

Argument xml_document :: parse() jest zakończonym znakiem zerowym łańcuchem zawierającym xml. Musisz więc utworzyć funkcję file2string. Odczytaj plik do bufora wektorowego , a następnie przeprowadź i buforuj [0], aby przeanalizować(). – anno

+0

vtd-xml ma również port C++, w porównaniu z rapidXML, vtd-xml jest znacznie bardziej zgodny, stabilny i wydajny ... –

Odpowiedz

0

manual mówi nam:

funkcja xml_document :: analizowania

[...] Analizuje zerowej zakończony XML ciąg według podanych flag.

RapidXML pozostawia ładowanie danych postaci z pliku do ciebie. Albo odczytaj plik do bufora, jak sugeruje anno lub ewentualnie użyj techniki mapowania pamięci. (Ale najpierw sprawdź flagę parse_non_destructive).

7

Sam w C++ ... ale chciałem się podzielić rozwiązaniem.

YMMV!

okrzyk SiCrane na ten thread: - i po prostu zastąpienie „string” wektorem --- (dzięki anno)

Proszę o komentarz i pomóż mi dowiedzieć się również! Jestem bardzo nowy na tym

W każdym razie, to wydaje się działać na dobry początek:

#include <iostream> 
#include <fstream> 
#include <vector> 

#include "../../rapidxml/rapidxml.hpp" 

using namespace std; 

int main(){ 
    ifstream myfile("sampleconfig.xml"); 
    rapidxml::xml_document<> doc; 

    /* "Read file into vector<char>" See linked thread above*/ 
    vector<char> buffer((istreambuf_iterator<char>(myfile)), istreambuf_iterator<char>()); 

    buffer.push_back('\0'); 

    cout<<&buffer[0]<<endl; /*test the buffer */ 

    doc.parse<0>(&buffer[0]); 

    cout << "Name of my first node is: " << doc.first_node()->name() << "\n"; /*test the xml_document */ 


} 
+0

Działa to dobrze, ale tylko wtedy, gdy "wektor bufor" nie jest poza zakresem: a Szybkim i brudnym sposobem rozwiązania tego problemu jest dodanie słowa kluczowego "statyczny" do wektora, ale nie sądzę, że jest to naprawdę czyste. Zobacz: http://stackoverflow.com/questions/6363719/rapidxml-reading-from-file-what-is-wrong-here – FlipMcF

2

zwykle czytamy XML z dysku do std::string, a następnie wykonać kopię bezpieczeństwa go w std::vector<char> jak pokazano poniżej:

string input_xml; 
string line; 
ifstream in("demo.xml"); 

// read file into input_xml 
while(getline(in,line)) 
    input_xml += line; 

// make a safe-to-modify copy of input_xml 
// (you should never modify the contents of an std::string directly) 
vector<char> xml_copy(input_xml.begin(), input_xml.end()); 
xml_copy.push_back('\0'); 

// only use xml_copy from here on! 
xml_document<> doc; 
// we are choosing to parse the XML declaration 
// parse_no_data_nodes prevents RapidXML from using the somewhat surprising 
// behavior of having both values and data nodes, and having data nodes take 
// precedence over values when printing 
// >>> note that this will skip parsing of CDATA nodes <<< 
doc.parse<parse_declaration_node | parse_no_data_nodes>(&xml_copy[0]); 

Pełną sprawdzania kodu źródłowego:

Read a line from xml file using C++

+0

To jest zbyt wolno ze względu na zmianę rozmiaru wektora. Porównaj z odpowiedzią Superfly Jona, jest znacznie szybsza. –

26

RapidXml jest dostarczany z klasą, która może to zrobić dla ciebie, rapidxml::file w pliku rapidxml_utils.hpp. Coś jak:

#include "rapidxml_utils.hpp" 

int main() { 
    rapidxml::file<> xmlFile("somefile.xml"); // Default template is char 
    rapidxml::xml_document<> doc; 
    doc.parse<0>(xmlFile.data()); 
... 
} 

Zauważ, że obiekt xmlFile zawiera teraz wszystkie dane do pliku XML, co oznacza, że ​​raz to wychodzi z zakresu i jest niszczona zmiennej doc nie jest już bezpiecznie użyteczny. Jeśli wywołasz parsowanie wewnątrz funkcji, musisz w jakiś sposób zachować obiekt w pamięci (zmienna globalna, nowa itd.), Aby dokument pozostał ważny.