RapidXML throwing a parse_error exception
When I try to parse a simple .xml file using the RapidXML framework, it throws a parse_error with this cause: "expected <". Now this is practically my first time writing XML code, so it might be a silly syntax error, in that case, bear with me :) This is my xmlParser.h:
#ifndef __XML_PARSER_H__
#define __XML_PARSER_H__开发者_Go百科
#include "rapidxml.hpp"
#include "windowUtil.h"
class XmlParser
{
public:
bool parse(char *xml)
{
try
{
doc.parse<0>(xml);
}
catch(rapidxml::parse_error &e)
{
msg_box(NULL, e.what(), "RapidXML exception!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
return false;
}
return true;
}
char* get_first_node_name()
{
return doc.first_node()->name();
}
private:
rapidxml::xml_document<> doc;
};
#endif
And this is how it is called and used:
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow)
{
XmlParser xmlParser;
WindowFramework *window = create_window(&framework, NULL, NULL, "GAME");
if(!init_window(window, true, true))
return kill(1);
if(!xmlParser.parse("./layouts/login_gui.xml"))
return kill(1);
framework.main_loop();
return kill(0);
}
login_gui.xml:
<?xml version="1.0"?>
<button>
<text>EXIT</text>
<buttonready>button.png</buttonready>
<buttonrollover>button_active.png</buttonrollover>
<buttonpressed>button_pressed.png</buttonpressed>
<buttoninactive>button_inactive.png</buttoninactive>
</button>
The parse
method takes a string containing XML, you are passing it a filename. Your filename is being treated as the XML data and obviously that's not right. You must read in the file first, and then call parse with the resulting string.
From the RapidXML docs:
function xml_document::parse
Synopsis
void parse(Ch *text);
Description
Parses zero-terminated XML string according to given flags.
Your revised structure could be something like
bool parse(char *xmlFile)
{
try
{
std::string xml(getXmlDataFromFile(xmlFile));
doc.parse<0>(xml.c_str());
}
There's a fine document on using RapidXML that I always refer to. It's a must read!
Here is my attempt to read the first nodes of your document (demo.xml).
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]);
// we didn't keep track of our previous traversal, so let's start again
// we can match nodes by name, skipping the xml declaration entirely
xml_node<>* cur_node = doc.first_node("button");
// go straight to the first text node
cur_node = cur_node->first_node("text");
string text = cur_node->value(); // if the node doesn't exist, this line will crash
cout << text << endl;
// and then to the next node
cur_node = cur_node->next_sibling("buttonready");
string b_ready = cur_node->value();
cout << b_ready << endl;
// and then to the next node
// ...
Outputs:
EXIT
button.png
If in the future your XML gets more complex, you could take a look at this answer:
Read a line from xml file using C++
which shows a source code that also read properties from nodes.
精彩评论