|
Hi Kyung-Min,
I am impressed with you work on XMLite XML parser in CodeProject. I see you
are a very good programmer.
I am stuck with the program I am writing regarding XML. I am wondering if
you can help me.
I need to add a XML code onto another XML file. For example:
In MyXML.xml:
<SUBAPPLICATION>
<GRAPH>
<ID Identity="G1">
<NAME>Haptic Audio Graphs</NAME>
<GRAPHICTYPE>Graph</GRAPHICTYPE>
<GRAPHICFORMAT>XLS, SVG</GRAPHICFORMAT>
</ID>
</GRAPH>
<MAP>
<ID Identity="M1">
<NAME>Haptic Audio Maps</NAME>
<GRAPHICTYPE>Map</GRAPHICTYPE>
<GRAPHICFORMAT>DAU, GIS, GLM</GRAPHICFORMAT>
</ID>
</MAP>
</SUBAPPLICATION>
And I have another xml code (xml 2):
<GRAPH>
<ID Identity="G2">
<NAME>Haptic Graphs</NAME>
<GRAPHICTYPE>Graph</GRAPHICTYPE>
<GRAPHICFORMAT>XLS</GRAPHICFORMAT>
</ID>
</GRAPH>
So I need to place xml code in xml 2 into my MyXML.xml code. So if it is
<GRAPH>, then it needs to be put under <GRAPH>. If it is <MAP>, then it
needs to be put under <MAP>. So for the example above, the output should be:
In MyXML.xml:
<SUBAPPLICATION>
<GRAPH>
<ID Identity="G1">
<NAME>Haptic Audio Graphs</NAME>
<GRAPHICTYPE>Graph</GRAPHICTYPE>
<GRAPHICFORMAT>XLS, SVG</GRAPHICFORMAT>
</ID>
<ID Identity="G2">
<NAME>Haptic Graphs</NAME>
<GRAPHICTYPE>Graph</GRAPHICTYPE>
<GRAPHICFORMAT>XLS</GRAPHICFORMAT>
</ID>
</GRAPH>
<MAP>
<ID Identity="M1">
<NAME>Haptic Audio Maps</NAME>
<GRAPHICTYPE>Map</GRAPHICTYPE>
<GRAPHICFORMAT>DAU, GIS, GLM</GRAPHICFORMAT>
</ID>
</MAP>
</SUBAPPLICATION>
If you know what I mean, can you give me some helps how I can do that? I am
trying to see if I can use any of your method.
Look forward to hearing from you. Please help....
Many thanks,
-----------------------------------
here is my answer.
a.xml is first xml file.
b.xml is second xml file.
int LoadFromFile(char* fpath, char* buf)
{
FILE* fp;
fp = fopen(fpath, "rt");
if( fp == NULL)
return 0;
fread(buf, 1, 1000, fp );
fclose(fp);
return 1;
}
void CTestXMLiteDlg::OnButton13()
{
// TODO: Add your control notification handler code here
char buf1[1000];
char buf2[1000];
XNode node1;
XNode node2;
if( LoadFromFile("a.xml", buf1) == 0 )
{
AfxMessageBox("no file a.xml");
return;
}
if( LoadFromFile("b.xml", buf2) == 0 )
{
AfxMessageBox("no file b.xml");
return;
}
if(node1.Load(buf1) == 0 )
{
AfxMessageBox("xml load fail a.xml");
return;
}
if(node2.Load(buf2) == 0 )
{
AfxMessageBox("xml load fail b.xml");
return;
}
// test show a.xml and b.xml
AfxMessageBox( node1.GetXML() );
AfxMessageBox( node2.GetXML() );
// now, find GRAPH node of a.xml to get inserting point.
LPXNode pNode = node1.Find("GRAPH");
if( pNode )
{
// test show GRAPH node of a.xml
AfxMessageBox( pNode->GetXML() );
// now, find ID nodes of b.xml to insert
XNodes childs_of_node2 = node2.GetChilds(_T("ID") );
for( int i = 0 ; i < childs_of_node2.size(); i++)
{
// insert node branch of b.xml's ID nodes to a.xml
pNode->AppendChildBranch(childs_of_node2[i]);
}
// test show result
AfxMessageBox( node1.GetXML() );
}
}
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
It is very useful. Thanks, bro. One thing, how to write the new XML to the file (a.xml) after adding the second file onto the first one? I think maybe "fwrite" will work, but its first parameter needs to be const void *. How can I do this? If possible, after the inserting, the next time I open a.xml, it would be the new node1.
Thanks a lot.
|
|
|
|
|
I have figure out how to do it. Thanks again for the code.... It is really a great one!
|
|
|
|
|
Hi, sorry... I just found an interesting thing. If you see my b.xml. I
realize when we tried to search for "ID" - node1.Find("ID");, it won't go
to the for loop. So I tried to search for "GRAPH" instead and it works. It
seems to me that the Find function can only search for the node after the
main node.
LPXNode pNode = node1.Find("GRAPH");
if( pNode )
{
// test show GRAPH node of a.xml
AfxMessageBox( pNode->GetXML() );
// now, find ID nodes of b.xml to insert
XNodes childs_of_node2 = node2.GetChilds(_T("ID") );
for( int i = 0 ; i < childs_of_node2.size(); i++)
{
// insert node branch of b.xml's ID nodes to a.xml
AfxMessageBox( childs_of_node2[i]->GetXML() );
pNode->AppendChildBranch(childs_of_node2[i]);
//AfxMessageBox(pNode.GetXML());
}
// test show result
AfxMessageBox( node1.GetXML() );
}
To conclude what I have mentioned in all the emails, there are two problems:
1. As above 2. When we ask to display a.xml, it only displays part of my
XML code, if the file has quite a long xml.
I am really sorry about so many emails. But I can see it is working! You
are a star. I have been struggling on this for quite some time. Thanks a
lot!
Best,
Chui-Chui
-------------
here is my answer.
hi.
problem is changed hierarchy on b.xml.
</SUBAPPLICATION>
<GRAPH>
<ID>
<NAME>ASDE</NAME>
<GRAPHICTYPE>Graph</GRAPHICTYPE>
<GRAPHICFORMAT>, XLS</GRAPHICFORMAT>
</ID>
</GRAPH>
</SUBAPPLICATION>
As you said, just GetChilds() search child nodes of one level.
If you want to do 'deep-search' of all level, then use Find().
so, more general approch is,
1. deep-search for ID node ( then xmlite search first matched ID node. )
2. in parent of matched ID node, just do GetChilds().
this version will works too on prev version of b.xml.
here is new answer.
i hope it help.
int LoadFromFile(char* fpath, char* buf)
{
FILE* fp;
fp = fopen(fpath, "rt");
if( fp == NULL)
return 0;
fread(buf, 1, 1000, fp );
fclose(fp);
return 1;
}
void CTestXMLiteDlg::OnButton13()
{
// TODO: Add your control notification handler code here
char buf1[1000];
char buf2[1000];
XNode node1;
XNode node2;
if( LoadFromFile("a.xml", buf1) == 0 )
{
AfxMessageBox("no file a.xml");
return;
}
if( LoadFromFile("b.xml", buf2) == 0 )
{
AfxMessageBox("no file b.xml");
return;
}
if(node1.Load(buf1) == 0 )
{
AfxMessageBox("xml load fail a.xml");
return;
}
if(node2.Load(buf2) == 0 )
{
AfxMessageBox("xml load fail b.xml");
return;
}
// test show a.xml and b.xml
AfxMessageBox( node1.GetXML() );
AfxMessageBox( node2.GetXML() );
// now, find GRAPH node of a.xml to get inserting point.
LPXNode pNode = node1.Find("GRAPH");
if( pNode )
{
// test show GRAPH node of a.xml
AfxMessageBox( pNode->GetXML() );
// now, find ID nodes of b.xml to insert
LPXNode pIDFirstMatchNode = node2.Find(_T("ID") );
if( pIDFirstMatchNode )
{
XNodes childs_of_node2 = pIDFirstMatchNode->parent->GetChilds(_T("ID") );
for( int i = 0 ; i < childs_of_node2.size(); i++)
{
// insert node branch of b.xml's ID nodes to a.xml
pNode->AppendChildBranch(childs_of_node2[i]);
}
}
// test show result
AfxMessageBox( node1.GetXML() );
}
}
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
this source helped me so much in my software projects, i hope u update it to provide compatibility across visual c++ editions (.net 2003 up).
|
|
|
|
|
I used XMLite in unicode,however,when I used the GetAttrValue() to get some data,the app always exit in error.
This is the testing code:
XNode xmlRoot;
PARSEINFO pi;
CString sxml;
sxml = _T("\
<TAddress desc='book of bro'>\
<TPerson type='me'><Name>Cho,Kyung Min</Name><Nick>bro</Nick></TPerson>\
<TPerson type='friend'><Name>Baik,Ji Hoon</Name><Nick>bjh</Nick></TPerson>\
<TPerson type=friend><Name>Bak,Gun Joo</Name><Nick>dichter</Nick></TPerson>\
<TInformation count='3'/>\
</TAddress>");
xmlRoot.Load(sxml,&pi);
AfxMessageBox(node->GetAttrValue(_T("desc")));
Could you find some way to solve the problem,Thank you!
-- modified at 14:36 Saturday 20th May, 2006
|
|
|
|
|
Hi. Having:
<dsdlog>
</dsdlog>
your code took the name of the node only as dsd. In _SetString, I think that you should consider changing:
<br />
memcpy( pss, psz, len );<br />
for this line:
<br />
_tcsncpy(pss, psz, len);<br />
I did the change and it is working now.
By the way, I'm using this code for Embedded Visual C++ 4 with Windows Mobile 2003, and it's giving a lot of problems. Any suggestion?
Regards,
FG.
A polar bear is a bear whose coordinates has been changed in terms of sine and cosine.
|
|
|
|
|
yes. you are right.
on now, i'm working on other subject..
and i haven't any duty on maintenance of XMLite.
but someone can modify XMLite freely.
and I hope it as i written.
Thanks..
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
You are using unicode strings, I guess.
There is another possible problem around the memcpy:
GetBufferSetLength() doesn't work with a terminating '\0'. So instead of having
LPTSTR pss = ps->GetBufferSetLength(len + 1 );
memcpy( pss, psz, len );
pss[len] = '\0';
This code would be more appropriate:
LPTSTR pss = ps->GetBufferSetLength(len);
memcpy( pss, psz, len );
The same in _tagXMLEntitys::Ref2Entity()( LPCTSTR str ):
LPTSTR esbuf = es.GetBufferSetLength( len );
and in _tagXMLEntitys::Entity2Ref( LPCTSTR str ):
LPTSTR sbuf = s.GetBufferSetLength( len );
means in _tagXMLEntitys::Entity2Ref( LPCTSTR str, LPTSTR estr, int estrlen ) the string terminater cannot be set anymore:
as well as in _tagXMLEntitys::Ref2Entity( LPCTSTR estr, LPTSTR str, int strlen ):
I can't think of a case when this could really make a difference, it's probably mere code sanitizing. But ever since I moved from VS6 to VS2008 I encountered strange crashes where CSimpleStringT is involved quite often. Maybe the new ATL string manager used in VC9 isn't as tolerant as the one in VC6...
|
|
|
|
|
when my xml like this
<?xml version="1.0" encoding="gb2312" ?>
<ListItem11>
<BookId>36027</BookId>
<CalledName>\\;</CalledName>
</ListItem11>
there got problems,thank you!
ww
-- modified at 1:22 Sunday 30th April, 2006
|
|
|
|
|
if you want get PI node (<?xml?>), then you must use XDoc, not XNode.
and XMLite's default escape character is '\'. and you can disable it.
here is answer.
void CTestXMLiteDlg::OnButton15()
{
// TODO: Add your control notification handler code here
CString sXML = "\
<?xml version=\"1.0\" encoding=\"gb2312\" ?>\
<ListItem11>\
<BookId>36027</BookId>\
<CalledName>\\\\;</CalledName>\
</ListItem11>\
";
XDoc node;
PARSEINFO piNoescape;
piNoescape.escape_value = 0;
if( node.Load( sXML, &piNoescape ) )
{
AfxMessageBox( node.GetXML() );
}
}
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
The following function will crash if called a second time, why?
void foo::foo()
{
XNode xml_lnk;
LPXNode link_node;
xml_lnk.name = "LINK_INFO";
link_node = xml_lnk.CreateNode("LINK","S GOYER RD ");
link_node->AppendAttr("id","0x08d3befa");
xml_lnk.AppendChild(link_node);
link_node = xml_lnk.CreateNode("LINK","E SOUTHWAY BLVD");
link_node->AppendAttr("id","0x08d3bef7");
xml_lnk.AppendChild(link_node);
XNode xml_ri;
xml_ri.name = "ROUTE_INFO";
xml_ri.AppendChild("ROUTE_INFO_ID","2");
xml_ri.AppendChild(&xml_lnk); //this crashes second foo is called
MessageBox(xml_ri.GetXML());
}
|
|
|
|
|
XNode object's destructor will be delete all child nodes.
xml_lnk is child of xml_ri.
so xml_ri's Close() try to delete xml_lnk object.
but it's illigal.
you have to use one XNode or use CopyNode() or CopyBranch().
-- modified at 19:44 Tuesday 7th November, 2006
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
Compiler retruns 7 errors like this.
.\XMLite.cpp(853) : error C2664: 'std::_Vector_iterator<_Ty,_Alloc>::_Vector_iterator(const std::_Vector_iterator<_Ty,_Alloc> &)' : cannot convert parameter 1 from 'int' to 'const std::_Vector_iterator<_Ty,_Alloc> &'
with
[
_Ty=LPXNode ,
_Alloc=std::allocator<LPXNode >
]
Reason: cannot convert from 'int' to 'const std::_Vector_iterator<_Ty,_Alloc>'
with
[
_Ty=LPXNode ,
_Alloc=std::allocator<LPXNode >
]
No constructor could take the source type, or constructor overload resolution was ambiguous
for this member function
<code>XNodes::iterator _tagXMLNode::GetChildIterator( LPXNode node )
{
XNodes::iterator it = childs.begin();
for( ; it != childs.end() ; ++(it) )
{
if( *it == node )
return it;
}
return NULL;
}</code>
Problem is that you cannot return NULL.
Is it correct when I change return NULL with return childs.end() ?
Palo
|
|
|
|
|
yes. it's my fault.
thanks for fix.
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
|
Hi, youbang zhang.
Thank you for your unicode version.
I will check it up and update info on xmlite page.
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
Where can I download unicode version of source code?
Specified link isn't yet valid.
Cho, Kyung-min, it will be hopeful add (publish) it on this page.
Thank you.
|
|
|
|
|
Hi Cho, Kyung-min,
Does the parser cope with multiple branches?
I tried the following XML in your examples, but only the first branch (AddressBook) seemed to be accessible:-
sxml = _T("<addressbook description="\"book" of="" bro\"="">\
<person type="me"><name>Cho,Kyung Min<nick>bro\
<person type="friend"><name>Baik,Ji Hoon<nick>bjh\
<person type="friend"><name>Bak,Gun Joo<nick>dichter\
<information count="3">\
\
<personaldirectory description="\"book" of="" friends\"="">\
<person type="me"><name>Clark,Peter<nick>Pete\
<person type="friend"><name>Ridler,Kevin<nick>Kev\
<person type="friend"><name>Hermes,Bernard<nick>Berni\
<information count="3">\
");
Should it be possible to access to the PersonalDirectory XML section ?
Many thanks,
Peter Clark
peterashleyclark@yahoo.co.uk
|
|
|
|
|
Hi, picnic.
XMLite process one root element.
in branch copy (deep-copy) section, that code is wrong on this page. (problem with html tag processing)
but source example code is works.
and if you want to multiple root elements, I wrote already about it before.
-------------------
XNode in XMLite can parse one element.
so, xnode.Load( "<a></a><b></b><c></c>" ) , then xnode parse only .
if you want to parse all elements, then write below
( somebody ask to me how to do this )
CString s;
s = _T("<a></a><b></b><c></c>");
XNode a,b,c;
LPTSTR pa = (LPTSTR)(LPCTSTR)s;
LPTSTR pb = a.Load( pa );
LPTSTR pc = b.Load( pb );
LPTSTR pNull = c.Load( pc );
TRACE(_T("%s %s %s"), a.name , b.name, c.name );
<h6>Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.</h6>
-- modified at 21:04 Wednesday 25th January, 2006
|
|
|
|
|
Hi,
I am working on my thesis that about doing a server application for a company.
thay have a Messenger (it's name is Cute Messenger) and thay want me to do a server application so it can do it possible to members of Cute Messenger that chat with thier friends on MSN messenger or ICQ or Yahoo messenger.
I am a newbie and I have hort that it can be possible by Jabber, I saw your aricle and i thought you maybe can help me and give some advice or tip.
you can write to me dirctly to my mail: arash22@hotmail.com
thank you so much.
and sorry about my bad english
arash
|
|
|
|
|
I worked with jabber server as you see on my introduction page, I choose win32 jaber com client library, but at that time, jabercom doesn't support korean language.
so i make own jaber client program. XMLite is a by-product in that project.
jabber.org shows how can talk with jabber server.
sorry for my poor english too.
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
In fact, XMLite has almost thought about UNICODE, but we need to make a little correcting work :
1. add these code to XMLite.h
<br />
#ifdef _UNICODE<br />
typedef std::wostringstream tostringstream;<br />
#define _tmemcpy wmemcpy<br />
#else<br />
typedef std::ostringstream tostringstream;<br />
#define _tmemcpy memcpy<br />
#endif<br />
2. some changes in XMLite.cpp
(1)find all "std::ostringstream", change them to "tostringstream"
(2)in function "_SetString", find
<br />
memcpy( pss, psz, len );<br />
change "memcpy" to "_tmemcpy"
then it seems work fine, but I've not tested a lot
|
|
|
|
|
Hi, Hewllet.
Thanks for your advice.
Your share thing will be help me and others.
Thank you all. No one know oneself all. My idea from you, book, all others. already we are shared brains.
|
|
|
|
|
Hi,
You can do this much simpler.
typedef std::basic_ostringstream<tchar, std::char_traits<tchar="">, std::allocator<tchar> > tostringstream;
|
|
|
|
|