xml parsing in c++ using tinyxml - c++

i am creating xml file in c++
i wrote the code like creating writing the xml file in c++ as shown below
const char* assign =
"<?xml version=\"1.0\" standalone='no' >\n"
"<office>"
"<work>file created</work>"
"</office>";
TiXmlDocument doc( "vls.xml" );
doc.Parse( assign );
if ( doc.Error() )
{
printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() );
exit( 1 );
}
doc.SaveFile();
bool loadOkay = doc.LoadFile();
if ( !loadOkay )
{
printf( "Could not load test file 'vls.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() );
exit( 1 );
}
else
printf(" 'vls.xml' loaded successfully");
but now i need only the data in the XMl file not the tags
guys plz help me.

I'd suggest reading the TinyXml documentation, more specifically the TiXmlElement documentation.
For your special case, I'd say it looks like that:
TiXmlElement * office = doc.FirstChildElement( "office" );
if( office )
{
TiXmlElement *work = office.FirstChildElement( "work" );
if( work )
{
printf("Work text: %s\n", work.GetText());
}
}
Although I'm not an expert with TinyXml.
FYI:
StackOverflow search function
Some - Answers - You - should have - considered ....
Please, search Google and StackOverflow before asking such trivial questions.

Related

Fetch geometry based on fields

if I have a datasource with only polygons, and each polygon has a field of
string, let's say its name, this name is unique for each geometry, they are
attributed dynamically
The more the name of a geometry is similar with another, the more the
geometries are close.
What I want to do is to fetch all the geometries for which the name begins
with something given by the user.
I looked GDAL's algorithms but it seems that nothing fits my problem, maybe
I didn't search enough, and I don't want to look at all the geometries to
find ones that fit.
Thanks,
EDIT :
As mentioned in the commentaries I didn't give any example of what I'm trying to do.
So, I'm using GDAL and OGR libraries (v1.11.0) in C++ because I have to work with raster and vector datas at the same time.
In my process I use the function GDALPolygonize() to extract the polygon, here an sample :
GDALDataset dataset; //this a dataset of int32
size_t width, height;
//Do something with the dataset
const char *pszDriverName = "ESRI Shapefile";
OGRSFDriver *poDriver;
OGRRegisterAll();
poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(
pszDriverName );
if( poDriver == NULL )
{
printf( "%s driver not available.\n", pszDriverName );
exit( 1 );
}
OGRDataSource *poDS;
poDS = poDriver->CreateDataSource("name.shp", NULL );
if( poDS == NULL )
{
printf( "Creation of output file failed.\n" );
exit( 1 );
}
OGRLayer *poLayer;
poLayer = poDS->CreateLayer( "region", NULL, wkbPolygon, NULL );
if( poLayer == NULL )
{
printf( "Layer creation failed.\n" );
exit( 1 );
}
OGRFieldDefn oField( "id", OFTString ); //I use string but there i can use another type
oField.SetWidth(32);
if( poLayer->CreateField( &oField ) != OGRERR_NONE )
{
printf( "Creating Name field failed.\n" );
exit( 1 );
}
GDALPolygonize(dataset->GetRasterBand(1), nullptr, poLayer, 0, nullptr, nullptr, nullptr);
OGRDataSource::DestroyDataSource( poDS );
GDALClose(dataset);
This code is mostly taken from the GDAL website.
So, I use the polygons given by OGRPolygon. Then, later, the user selected a polygon and the goal is to find those who share a certain number of bits.
Thanks to GDAL I can use, the OGRFeature and OGRField, but my only idea is to list each polygons, but i'm sure there is better way to accomplish this task
Hopefully it clearer.
An efficient way is to implement this as a lookup in a radix tree.

Qt Read XML File

I am trying to read an xml file in Qt, which I successfully generated using a different method. Here is my xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Project>
<EditorTheme>NULL</EditorTheme>
<Modules>
<Module>
<Name>Module_Renderer</Name>
<Position>471,164</Position>
<Size>200,100</Size>
<Locked>true</Locked>
<Visible>true</Visible>
</Module>
<Module>
<Name>Module_Console</Name>
<Position>200,229</Position>
<Size>256,192</Size>
<Locked>true</Locked>
<Visible>false</Visible>
</Module>
<Module>
<Name>Module_ResourceToolkit</Name>
<Position>1049,328</Position>
<Size>200,100</Size>
<Locked>true</Locked>
<Visible>true</Visible>
</Module>
<Module>
<Name>Module_CellEditor</Name>
<Position>542,564</Position>
<Size>200,100</Size>
<Locked>true</Locked>
<Visible>false</Visible>
</Module>
</Modules>
</Project>
And here is some code that I am using to parse this file:
Project ProjectLoader::loadLastProject( ConsoleModule* console ) {
Project project;
// load xml
QFile file( "C:/Users/Krynn/Desktop/LastProject.xml" );
if( !file.open( QFile::ReadOnly | QFile::Text ) ) {
// print error cannot open
}
QXmlStreamReader reader;
console->outputDisplay->append( "Test" );
reader.setDevice( &file );
reader.readNext();
while( !reader.atEnd() && !reader.hasError() ) {
reader.readNext();
if( reader.isStartElement() ) {
QString name = reader.name().toString();
if( reader.name() == "Project" ) {
reader.readNextStartElement();
if( reader.name().toString() == "EditorTheme" ) {
// Append Project theme
console->outputDisplay->append( "Theme Detected: " + reader.name().toString() + " " + reader.readElementText() );
}
reader.readNextStartElement();
if( reader.name().toString() == "Modules" ) {
// how do I proceed??
console->outputDisplay->append( QString( "" ) + " " + reader.name().toString() + " " + reader.readElementText() );
}
}
}
}
if( reader.hasError() ) {
console->outputDisplay->append( "XML error: " + reader.errorString() );
} else if( reader.atEnd() ) {
console->outputDisplay->append( "End of XML File Reached" );
}
file.close();
return project;
}
And here is some visual output for what that code gives me:
Really, I just don't know how I would go about loading all the module data within the xml file. I was using a plain text file previously to store all this stuff, but now I want to upgrade. Any help would be greatly appreciated.
Nevermind I figured it out.
Project ProjectLoader::loadLastProject( ConsoleModule* console ) {
Project project;
// load xml
QFile file( "C:/Users/Krynn/Desktop/LastProject.xml" );
if( !file.open( QFile::ReadOnly | QFile::Text ) ) {
// print error cannot open
}
QXmlStreamReader reader;
reader.setDevice( &file );
reader.readNext();
int count = 0;
while( !reader.atEnd() ) { //&& !reader.hasError()
reader.readNext();
if( reader.isStartElement() ) {
if( reader.name().toString() == "Module" ) {
WindowModuleSaveData data;
reader.readNextStartElement();
data.name = reader.readElementText(); // name
reader.readNextStartElement();
data.position = convertStringToQPoint( reader.readElementText() );
console->outputDisplay->append( convertQPointToString(data.position) );
reader.readNextStartElement();
data.size = convertStringToQSize( reader.readElementText() );
reader.readNextStartElement();
data.isLocked = reader.readElementText() == "true" ? true : false;
reader.readNextStartElement();
data.isVisible = reader.readElementText() == "true" ? true : false;
project.modules.push_back( data );
console->outputDisplay->append("Loaded A Module");
}
count++;
}
}
console->outputDisplay->append( QString::number( count ) );
if( reader.hasError() ) {
console->outputDisplay->append( "XML error: " + reader.errorString() );
} else if( reader.atEnd() ) {
console->outputDisplay->append( "End of XML File Reached" );
}
file.close();
return project;
}
The above code may be error prone, because it assumes what the next child may be instead of actually testing for it. Good enough for now though.

get data in other .cpp file

Im working on an online game and I have a problem with getting the ms-sql results into a other cpp file.
cpp file1 to start the query:
databaseManager.Query( hDB, new CQuery_AuthServer(req->awchUserId, req->awchPasswd);
req->awchUserId and req->awchPasswd are data from socket (username and password)
now on cpp file2 I execute the query inside a class
class CQuery_AuthServer : public CNtlQuery
{
public:
CQuery_AuthServer(const WCHAR * lpszUserID, const WCHAR * lpszUserPW)
{
ZeroMemory( m_szUserID, MAX_SIZE_USER_ID + 1 );
ZeroMemory( m_szUserPW, MAX_SIZE_USER_PW + 1 );
memcpy(m_szUserID, lpszUserID, MAX_SIZE_USER_ID);
memcpy(m_szUserPW, lpszUserPW, MAX_SIZE_USER_PW);
}
int ExecuteQuery(CNtlDatabaseConnection * pConnection)
{
FIND_SQLUNIT( SP_AuthLogin, pConnection, pSqlUnit2 );
if( NULL == pSqlUnit2 )
{
return NTL_FAIL;
}
strncpy_s( pSqlUnit2->m_szUserID, m_szUserID, MAX_SIZE_USER_ID );
strncpy_s( pSqlUnit2->m_szUserPW, m_szUserPW, MAX_SIZE_USER_ID );
pSqlUnit2->Exec();
printf("ExecuteQuery Done: result: %i ACC ID: %i \n", pSqlUnit2->m_nResultCode, pSqlUnit2->m_dwAccountID );
return NTL_SUCCESS;
}
public:
char m_szUserID[MAX_SIZE_USER_ID + 1];
char m_szUserPW[MAX_SIZE_USER_PW + 1];
};
This is needed for the query
BEGIN_DECLARE_SQLUNIT( SP_AuthLogin, "{ ? = call AuthLogin(?,?,?) }" )
BEGIN_VARIABLE()
char m_szUserID[MAX_SIZE_USER_ID + 1];
char m_szUserPW[MAX_SIZE_USER_PW + 1];
int m_dwAccountID;
int m_nResultCode;
END_VARIABLE()
BEGIN_PARAM(3)
PARAM_ENTRY(SQL_PARAM_OUTPUT, m_nResultCode)
PARAM_ENTRY_STR(SQL_PARAM_INPUT, m_szUserID)
PARAM_ENTRY_STR(SQL_PARAM_INPUT, m_szUserPW)
PARAM_ENTRY(SQL_PARAM_OUTPUT, m_dwAccountID)
END_PARAM()
END_DECLARE_SQLUNIT()
Now I can get the result but the result only works inside int ExecuteQuery
The query results are:
pSqlUnit2->m_nResultCode
pSqlUnit2->m_dwAccountID
how can I get those 2 results in the first cpp file where I made the query?
edit: the first cpp file:
void CClientSession::SendCharLogInReq(CNtlPacket * pPacket)
{
sUA_LOGIN_REQ * req = (sUA_LOGIN_REQ *)pPacket->GetPacketData();
HDATABASE hDB = INVALID_HDATABASE;
CNtlDatabaseManager databaseManager;
databaseManager.Query( hDB, new CQuery_AuthServer(req->awchUserId, req->awchPasswd) );
//WANT RESULT HERE
}
I dont really know what to do.. Im really newbie
here is the complete source https://www.sendspace.com/file/oc5v34
at PacketAuthServer.cpp I run the query
at AuthQueryServer.h I execute the query
Disregard the previous answer. The problem with the previous answer is that it was expecting databaseManager.Query to be syncrhonous, and to execute CQuery_AuthServer::ExecuteQuery before it returns to the caller. In fact it doesn't - it just adds the query to the queue, and your database management framework doesn't give you the ability to wait for completion of that query.
You should read the NtlDatabase manual to know how to make synchronous database calls

"Unable to read memory" When using "FILE* file" (C++) on WindowPhone8

i got problem when using "FILE* file;" with C++ on WP8.
My app crash when meet the line above.
When i debug, i saw:
1. All the member of this variable "file" got message:
(file)->_ptr: Unable to read memory.
(file)->_cnt: Unable to read memory.
(file)->_base: Unable to read memory.
(file)->_flag: Unable to read memory.
(file)->_file: Unable to read memory.
(file)->_charbuf: Unable to read memory.
(file)->_tmpfname: Unable to read memory.
(file)->_bufsiz: Unable to read memory.
I have no idea to fix it.
And this is the code i Use:
void SubMenu::LoadConfig(float dt)
{
TiXmlDocument doc;
bool flag = doc.LoadFile("Config\Config.xml");// Error here.
TiXmlElement* root = doc.FirstChildElement();
for (TiXmlElement* elem = root->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement())
{
std::string elemName = elem->Value();
int Star = atoi(elem->GetText());
if (elemName == "Tractor")
{
this->AddStarPoint(Level1, 4, Star);
}
if (elemName == "EggsCatch")
{
this->AddStarPoint(Level2, 3, Star);
}
if (elemName == "EggsCatch2")
{
this->AddStarPoint(Level3, 4, Star);
}
}
}
This is tinyxml.cpp got function LoadFile:
bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
{
TIXML_STRING filename( _filename );
value = filename;
// reading in binary mode so that tinyxml can normalize the EOL
FILE* file = TiXmlFOpen( value.c_str (), "rb" ); // Error here.
if ( file )
{
bool result = LoadFile( file, encoding );
fclose( file );
return result;
}
else
{
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
}
Please help!
Thanks!
I suppose file == NULL because of a single backslash \ in the path. Try
(simpler) replacing it with a slash "Config/Config.xml", or
(better) escape it with another backslash "Config\\Config.xml".

How to create database connectivity through C++

In C++, how can I establish an SQL connection to store data in an SQL database?
You should have a look at C preprocessors that exists traditionaly with databases (ecpg for postgres, Pro*C for oracle ... which lets you embed straight SQL directly in your source files) or an orginal system for mysql. ECPG will do with C++, that is/was not the case for some other preprocessors ...
IF you are targetting Windows, then you might want to use ODBC.
you could try wxSqlite with SQLite as Database. This offers you an open source connection header / c++ file to get started.
In general - you should get some kind of library that offers you the required functionality. All major DB vendors should offer at least a C library. Most of the time you get a C++ library or wrapper for the C one.
Use SQLAPI++ - it's cross platform and supports MS SQL Server, Oracle, Postgres and others. Very easy to use.
http://www.sqlapi.com/
If you targeting windows you can always use the import ability.
#import "c:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename( "EOF", "EndOfFile" )
Then you could make a wrapper to deal with the SQL.
Little example, just to open close a connection
// H
class CExtAdoDatabase
{
public:
CExtAdoDatabase( const char* p_cConnectString="", const char* p_cUsername="", const char* p_cPwd="" );
virtual ~CExtAdoDatabase();
bool Open( const char* p_cConnectString="", const char* p_cUsername="", const char* p_cPwd="" );
bool Close();
private:
HRESULT _hInitRes;
bool _bIsValid;
_ConnectionPtr *_p_pConnection;
};
// CPP
CExtAdoDatabase::CExtAdoDatabase( const char* p_cConnectString, const char* p_cUsername, const char* p_cPwd ) : _hInitRes( CoInitialize( NULL ))
{
_p_pConnection = new _ConnectionPtr( "ADODB.Connection" );
if( FAILED( _hInitRes ))
_bIsValid = false;
else
{
_bIsValid = true;
(*_p_pConnection)->ConnectionTimeout=0;
(*_p_pConnection)->CommandTimeout=0;
if( p_cConnectString != NULL && strlen(p_cConnectString) )
{
_bstr_t scs( p_cConnectString );
_bstr_t susr( p_cUsername );
_bstr_t spwd( p_cPwd );
(*_p_pConnection)->Open( scs, susr, spwd, NULL );
}
}
}
CExtAdoDatabase::~CExtAdoDatabase()
{
Close();
delete _p_pConnection;
CoUninitialize();
}
bool CExtAdoDatabase::Open( const char* p_cConnectString, const char* p_cUsername, const char* p_cPwd )
{
if(_bIsValid)
{
_bstr_t scs( p_cConnectString );
_bstr_t susr( p_cUsername );
_bstr_t spwd( p_cPwd );
return ((*_p_pConnection)->Open( scs, susr, spwd, NULL ) == S_OK);
}
else
return false;
}
bool CExtAdoDatabase::Close()
{
if( _bIsValid )
{
if( (*_p_pConnection)->GetState() == adStateOpen )
return !!(*_p_pConnection)->Close();
else
return true;
}
else
return false;
}