2013-08-23 4 views
0

Я пытаюсь использовать для анализа моего XML-файла. И я сделал это после example here. Вместо того, чтобы выполнять синтаксический анализ в основной функции, я написал класс оболочки, называемый XMLParser, для выполнения задания синтаксического анализа. И это действительно дает мне головную боль.C++ Использование RapidXml для разбора XML-файла, класса Wrapper, parse_error ожидать>

XMLParser.hpp:

#include <iostream> 
#include <string> 
#include <stdio.h> 
#include <vector> 
#include "rapidxml/rapidxml.hpp" 

using namespace std; 
using namespace rapidxml; 

class XMLParser { 

public: 
    XMLParser() {}; 

    XMLParser(const std::string &xmlString): xmlCharVector(xmlString.begin(), xmlString.end()) 
    { 
     //xmlCharVector.push_back('\0'); 
     parseXML(); 
    } 
    XMLParser(const std::vector<char> &_xmlVector):xmlCharVector(_xmlVector) 
    { 
     /* xmlCharVector.push_back('\0'); */ // already done in main.cpp 
     if (xmlCharVector != _xmlVector)  //And it turns out they're the same.... 
      std::cout << "The two vectors are not equal" << std::endl; 
     else 
      std::cout << "They are the same" << std::endl; 
     parseXML(); 
    } 

private: 
    std::vector<char> xmlCharVector; 
    rapidxml::xml_document<> doc; 
    void parseXML(); 

}; 

XMLParser.cpp:

#include "XMLParser.hpp" 

using namespace std; 
using namespace rapidxml; 

void XMLParser::parseXML() 
{ 
    doc.parse<0>(&xmlCharVector[0]); 
} 

А вот main.cpp:

#include <iostream> 
#include <stdio.h> 
#include <string> 
#include <vector> 
#include <fstream> 
#include "XMLParser.hpp" 

using namespace std; 
using namespace rapidxml; 

int main(int argc, char **argv) 
{ 
    xml_document<> doc; 
    xml_node<> *root_node; 
    ifstream theFile("beer.xml"); 
    vector<char> buffer((istreambuf_iterator<char>(theFile)), istreambuf_iterator<char>()); 
    buffer.push_back('\0'); 

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

    root_node = doc.first_node("MyBeerJournal"); 
    xml_node<> *engine = root_node->first_node("Brewery"); 

    //The above code works pretty well, and I can get the element I want in XML file. 

    //The problem occurs when I tried to use the XMLParser 
    XMLParser xmlParser(buffer); 
    return 0; 
} 

Процесс синтаксического анализа в основной функции работает очень хорошо. Но когда я пытался использовать функцию в моей обертку класса parseXML(), то произошла ошибка:

Terminate вызывается после метания экземпляр «rapidxml :: parse_error» , что(): ожидаемый> Abort (ядро сбрасывали)

Первоначально у меня есть другой код в этой функции, но я прокомментировал их все и обнаружил, что даже с одной строкой doc.parse<0>(&xmlCharVector[0]);. Почему он хорошо работает в main.cpp, а не в классе-оболочке? Я действительно не могу понять это. Может ли кто-нибудь помочь мне?

ответ

0

Я выяснил причину ... Эта глупая проблема на самом деле занимает много времени для отладки. Я пишу это здесь, чтобы кто-нибудь наткнулся на него (надеюсь, что нет) может сэкономить свое время. Проблема заключается именно в коде doc.parse<0>(&buffer[0]) в функции main. Перед выполнением этой строки кода, то buffer(type of vector<char>) как это: (напечатав вектор утешать)

<MyBeerJournal> 
    <Brewery name="Founders Brewing Company" location="Grand Rapids, MI"> 
     <Beer name="Centennial" description="IPA" rating="A+" dateSampled="01/02/2011"> 
      "What an excellent IPA. This is the most delicious beer I have ever tasted!" 
     </Beer> 
    </Brewery> 
    ..... 
    ..... 
</MyBeerJournal> 

Это то же самое с исходным файлом XML. После выполнения вышеуказанного кода, buffer(type of vector<char>) становится чем-то вроде этого:

<MyBeerJournal 
    <Breweryname"Founders Brewing Company location"Grand Rapids, MI> 

     <Beername"Centennial description"IPA rating"A+ dateSampled"01/02/2011> 

      "What an excellent IPA. This is the most delicious beer I have ever tasted!" 
     /Beer> 

    </Brewery> 

Как вы можете видеть, некоторые ангельские скобки исчезли. и некоторые другие вещи, такие как двойная кавычка, также были изменены. Таким образом, конструктор класса-оболочки скопировал измененный «xml-буфер», и этот не хорошо отформатированный вектор xml, безусловно, вызовет отказ второго doc.parse<0>(&xmlCharVector[0]); в классе-оболочке. Я не знаю, почему библиотечный писатель должен изменить переданный вектор char, потому что последующий анализ xml не имеет отношения к исходному символу char после создания DOC.

+0

* «Я не знаю, почему библиотечный писатель должен изменить вектор символов, переданный в * *. Поскольку RapidXML разработан как сверхбыстрый * in-situ * парсер. Созданный DOM представляет собой просто набор указателей в исходные данные. Прочтите документы, * конкретно * раздел о «отличиях от обычных парсеров XML». http://rapidxml.sourceforge.net/manual.html – Roddy

+0

@Roddy Это означает, что функция будет редактировать исходную строку напрямую с помощью указателя, а не сначала скопировать его, а затем сделать что-то на скопированном? – Dreamer

+0

Точно: он помещает нулевые символы для завершения каждого «узла», если вы не используете «неразрушающий» режим. Это позволяет избежать накладных расходов на скорость распределения памяти для хранения каждого узла и накладных расходов на память, требующих второй немодифицированной копии. – Roddy

 Смежные вопросы

  • Нет связанных вопросов^_^