I'd need a little hint on this little question:
I have a xml file I want to navigate and I have a library to process
it. But I want also to manage that file as an object to make clear and
efficient code.
So I coded two class which one is like recursive as like as in this
example:
class B : public xmlnode
{
public:
B(xmlnode* member);
LPCSTR getattribute(....);
void setattribute(....);
xmlnode* Node(LPCSTR nodename, LPCSTR attributenodename, LPCSTR
attributetosearch);
};
class A : public xmldocument
{
public:
A(LPCSTR xmlfilename);
xmlnode* Node(LPCSTR nodename, LPCSTR attributenodename,
LPCSTR attributetosearch);
};
So I can do this:
A* xmlobject = new A(filenamexmlblahblah);
xmlobject->Node(....,....,...)->Node(...,...,...)->GetAttribute(...);
where next nodes are nodes inside a parent node...but I get this link
error:
error LNK2019: unresolved external symbol "public: class B *
__thiscall B::Node(....)" ....
what I could have missed?...
Even I'm just using a function that returns class node itself....
Thanks to everyone!
Ciao
Luigi
You appear to have missed writing the B:Node method. You've got the
declaration of it in the header file, but no implementation.
Dave
I implemented the function in the .cpp as:
xmlnode* xmlnode::Node(LPCSTR nodename, LPCSTR attributenodename,
LPCSTR
attributetosearch)
{
....
}
but I still get that linker error....
code is this:
class B : public xmlnode
{
public:
B(xmlnode* member);
LPCSTR getattribute(....);
void setattribute(....);
B* Node(LPCSTR nodename, LPCSTR attributenodename, LPCSTR
attributetosearch);
};
class A : public xmldocument
{
public:
A(LPCSTR xmlfilename);
B* Node(LPCSTR nodename, LPCSTR attributenodename,
LPCSTR attributetosearch);
};
B* B::Node(LPCSTR nodename, LPCSTR attributenodename,
LPCSTR
attributetosearch)
{
....
}
and I get that linker error...
I can't immediately see what's wrong from what you've mentioned, but
clearly the linker is telling you that it can't link in the B::Node
method.
Dave
>Hello everyone!!!
>
>I'd need a little hint on this little question:
>
>I have a xml file I want to navigate and I have a library to process
>it. But I want also to manage that file as an object to make clear and
>efficient code.
>So I coded two class which one is like recursive as like as in this
>example:
>
>class B : public xmlnode
>{
>public:
> B(xmlnode* member);
>
> LPCSTR getattribute(....);
***
The use of LPCSTR seems a bit odd in an MFC program; CString would be better
****
> void setattribute(....);
>
> xmlnode* Node(LPCSTR nodename, LPCSTR attributenodename, LPCSTR
>attributetosearch);
>};
>
>class A : public xmldocument
>{
>public:
> A(LPCSTR xmlfilename);
>
> xmlnode* Node(LPCSTR nodename, LPCSTR attributenodename,
>LPCSTR attributetosearch);
>};
>
>So I can do this:
>
>A* xmlobject = new A(filenamexmlblahblah);
>xmlobject->Node(....,....,...)->Node(...,...,...)->GetAttribute(...);
>
>where next nodes are nodes inside a parent node...but I get this link
>error:
>
>error LNK2019: unresolved external symbol "public: class B *
>__thiscall B::Node(....)" ....
>
>what I could have missed?...
****
So did you define the Node() function? You declared it, but did you actually put it in
the .cpp file?
****
>Even I'm just using a function that returns class node itself....
****
See above. You probably didn't define it!
****
>
>Thanks to everyone!
>Ciao
>Luigi
Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
****
Why are you declaring B* B::Node in A? That doesn't seem to make sense.
joe
***
>
>and I get that linker error...
i'll explain better my situation: I have a XML file and I'm using
tinyxml to elaborate it... so I wanted just to navigate nodes and to
set/get attributes in this way:
MyDocument->Node(nodename, attributenodename, attributetosearch)->Node
(nodename, attributenodename, attributetosearch)->GetAttribute
(attributename);
so I created first class for the node MyNode:
class MyNode : public TiXmlNode
{
public:
MyNode() { };
LPCSTR GetAttribute( LPCSTR attributename) { blah blah blah
return LPCSTR;} ;
void SetAttribute(LPCSTR attributename, LPCSTR attributevalue)
{blah blah blah };
MyNode* Node( LPCSTR nodename, LPCSTR attributenodename,
LPCSTR attributetosearch )
{ blah blah blah };
};
then I created second class for the document MyDocument so it would
already see MyNode:
class MyDocument : public TiXmlDocument
{
MyDocument(LPCSTR filename) { blah blah blah };
MyNode* Node( LPCSTR nodename, LPCSTR attributenodename,
LPCSTR attributetosearch )
{ MyNode::Node(nodename, attributenodename,
attributetosearch); };
};
so each Node call would return a new node to navigate inside the node
itself...but looks like it doesn't compile correctly... How it should
be?...
Thanks
Ciao
Luigi
In class MyDocument you have
MyNode* Node( LPCSTR nodename, LPCSTR attributenodename,
LPCSTR attributetosearch )
{
MyNode::Node(nodename, attributenodename, attributetosearch);
}
Firstly, there is no return quantity in your definition. Secondly, you are
calling a non-static method of Node without an object.
In future, if you are having linker errors, it would be good if you could post
actual code that compiles.
--
David Wilkinson
Visual C++ MVP
#include "tinyxml/tinyxml.h"
class documentTinyNode : public TiXmlNode
{
public:
documentTinyNode(); // CTOR object TiXmlNode
~documentTinyNode() { };
LPCSTR GetAttribute( LPCSTR attributename ) { return ToElement
()->Attribute( attributename ); } // function class returns
attribute
void SetAttribute( LPCSTR attributename, LPCSTR
attributevalue ) { ToElement()->SetAttribute( attributename,
attributevalue ); } // function class sets attribute
documentTinyNode* Node( LPCSTR nodename, LPCSTR
attributenodename, LPCSTR attributetosearch ) // function class
returns new node
{
FirstChild(nodename);
LPCSTR currentnodename = ToElement()->Attribute
(attributenodename);
while ( (currentnodename != NULL) && (strcmp
(currentnodename, attributetosearch) != 0) ) {
IterateChildren(nodename , this);
currentnodename = ToElement()->Attribute
(attributenodename);
}
return ( (currentnodename != NULL) ? this : NULL );
}
};
class documentTinyXML : public TiXmlDocument
{
public:
documentTinyXML( LPCSTR xmlfilename ); // CTOR object
TiXmlDocument
~documentTinyXML() { };
documentTinyNode* Node( LPCSTR nodename, LPCSTR
attributenodename, LPCSTR attributetosearch ) // function returns
object class TiXmlNode
{
documentTinyNode::Node(nodename, attributenodename,
attributetosearch);
}); // function returns object class TiXmlNode
};
indeed in .CPP file I put:
documentTinyXML::documentTinyXML( LPCSTR xmlfilename )
{
if (!LoadFile( xmlfilename ))
AfxGetMainWnd()->MessageBox(_T("Error! Can't load xml
configuration file!\nIt could be not present or broken."), _T("MFC
Analyzer GUI"), MB_ICONSTOP | MB_OK);
}
void Ctest_tinyxmlDlg::OnBnClickedButton1()
{
//<?xml version="1.0" ?>
//<analyzer>
// <module name="system-manager">
// <sentence header="enableModules">
// <row-info name="system-manager"
value="1" />
// <row-info name="input-manager"
value="1" />
// <row-info name="output-manager"
value="1" />
// </sentence>
// </module>
// <module name="input-manager">
// <sentence header="output-type">
// <row-info name="out" value="1"
description="whatever-it-is" />
// </sentence>
// </module>
// <module name="output-manager">
// <sentence header="output-type">
// <row-info name="out" value="1"
description="whatever-it-is" />
// </sentence>
// </module>
//</analyzer>
documentTinyXML* xmldocument = new documentTinyXML
( "example.xml" );
LPCSTR pValue = xmldocument->Node("module","name","system-
manager")->Node("sentence","header","enableModules")->Node("row-
info","name","system-manager")->GetAttribute("value");
GetDlgItem(IDC_EDIT1)->SetWindowText( (LPCTSTR)pValue );
}
As you can see I’d like to start from TiXmlDocument’s type member
variable, getting deeper nodes to decide where to navigate since I
could have same sentences in different sublevels… how I could do
that?...
Thanks
ciao
Luigi