It's my first time using XML and I am currently trying to return an integer (actually want to return a double but haven't got that far yet) from an XML-file using C++. I'm using RAPIDXML and the following implementation:
All files are in the same directory.
XML (firstxml.xml):
<?xml version="1.0"?>
<test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="firstxsd.xsd">
<A>10</A>
<B>Hello</B>
</test>
XML-Schema (firstxsd.xsd):
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="test">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:integer" name="A"/>
<xs:element type="xs:string" name="B"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
C++ (test.cxx):
#include <iostream>
#include <sstream>
#include <fstream>
#include "rapidxml-1.13/rapidxml.hpp"
#include "rapidxml-1.13/rapidxml_print.hpp"
#include <string>
#include <stdio.h>
#include <vector>
int main(int argc, char* argv[])
{
std::ifstream file ("firstxml.xml");
if (file.is_open())
{
file.seekg(0,std::ios::end);
int size = file.tellg();
file.seekg(0,std::ios::beg);
char* buffer = new char [size];
file.read (buffer, size);
file.close();
rapidxml::xml_document<> doc;
doc.parse<0>(buffer);
rapidxml::xml_node<> *node = doc.first_node()->first_node();
//Line which results in error
std::cout << node->value()*10 << std::endl;
delete[] buffer;
}
}
The error:
test.cxx:52:31: error: invalid operands of types ‘char*’ and ‘int’ to binary ‘operator*’
From the tutorials I have read online, I believe I am constructing the files correctly and so the value parsed into the C++ file from the node A should be an integer. One thing I did notice is that in the RAPIDXML manual the specification of value() is as follows:
Ch* value() const;
Description: Gets value of node. Interpretation of value depends on type of node. Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. Use value_size() function to determine length of the value.
Returns: Value of node, or empty string if node has no value.
So the function definition says it always returns a character pointer, but the line "Interpretation of value depends on type of node" implies it returns a type-dependant value.
Thank you for taking the time to look at my issue, any help is greatly appreciated,
Paul.
I guess you want to access "attribute" value, so do something like ...
cout << "Name of my first node is: " << doc.first_node()->name() << "\n";
xml_node<> *node = doc.first_node("foobar");
cout << "Node foobar has value " << node->value() << "\n";
for (xml_attribute<> *attr = node->first_attribute(); attr; attr = attr->next_attribute())
{ cout << "Node foobar has attribute " << attr->name() << " ";
}
And also have a look at rapidXML tutorial...
http://rapidxml.sourceforge.net/manual.html its easy!
It is hard to say what does the phrase "Interpretation of value depends on type of node" mean. If the function returns
Ch pointer
it will always return such pointer or cause a runtime exception, if library developers provided such feature. Naturally, when you try to multiply aCh*
by an int you get compile time error.The only way a function can return a type which depends on call context is to use some special user-defined return type (
VARIANT
or something like it). It seems to me thatCh
is just a pseudonim for the basic character type of the library (char
or maybewchar_t
).So by that "interpretation..." notice developers probably meant that the user must make a proper interpretation of the character string in accordance to the type of node (which in turn depends on the user-defined schema).
To convert a C-string representation of a number to corresponding types you may use functions from the standard C library, such as
atoi()
(converts to int),atof()
(to double) and so on.Someone correct me if I'm wrong, I believe RapidXML will only give you values as some form of string due to its in-place parsing nature. The class templating might be for handling char vs wide char or something like that, I don't know, I only use char.
What I did to handle extracting values was to add a helper class to rapidxml_utils.hpp (could really have put it anywhere but it made sense there) with some static functions to parse a xml node or attribute to a value (or a default value if it doesn't parse).
These helpers have allowed me to do stuff like:
In your case you might use my helper class like this:
My helper class looks like this (I used sscanf to get some level of validation):
Hopefully this may be helpful to you or someone else using rapidxml and needing a quick way to get integers, doubles, or whatever out of nodes. It can certainly be expanded to other types, I only have types I've needed so far in there now, but you get the gist of it.