sometimes it can be useful to include XML data as a static string in a project.
as far as i could see there is no way to load data this way...
altough i'm new to TinyXml, it was fairly easy to add that functionalitiy.
i've just split up the LoadFile function, that's all. there was no additional code needed.
the name LoadFile might be unsuitable though. it's a quick hack anyway,
but might be of interest for further versions, maybe, so i'll post the code here:
// Get the file size, so we can pre-allocate the string. HUGE speed impact.
long length = 0;
fseek( file, 0, SEEK_END );
length = ftell( file );
fseek( file, 0, SEEK_SET );
// Strange case, but good to handle up front.
if ( length <= 0 )
{
SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
// If we have a file, assume it is all one big XML file, and read it in.
// The document parser may decide the document ends sooner than the entire file, however.
TIXML_STRING data;
data.reserve( length );
// Subtle bug here. TinyXml did use fgets. But from the XML spec:
// 2.11 End-of-Line Handling
// <snip>
// <quote>
// ...the XML processor MUST behave as if it normalized all line breaks in external
// parsed entities (including the document entity) on input, before parsing, by translating
// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
// a single #xA character.
// </quote>
//
// It is not clear fgets does that, and certainly isn't clear it works cross platform.
// Generally, you expect fgets to translate from the convention of the OS to the c/unix
// convention, and not work generally.
bool TiXmlDocument::LoadFile( const char *buf, long length, TiXmlEncoding encoding )
{
// Delete the existing data:
Clear();
location.Clear();
// Strange case, but good to handle up front.
if ( length <= 0 )
{
SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
// If we have a file, assume it is all one big XML file, and read it in.
// The document parser may decide the document ends sooner than the entire file, however.
TIXML_STRING data;
data.reserve( length );
// Subtle bug here. TinyXml did use fgets. But from the XML spec:
// 2.11 End-of-Line Handling
// <snip>
// <quote>
// ...the XML processor MUST behave as if it normalized all line breaks in external
// parsed entities (including the document entity) on input, before parsing, by translating
// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
// a single #xA character.
// </quote>
//
// It is not clear fgets does that, and certainly isn't clear it works cross platform.
// Generally, you expect fgets to translate from the convention of the OS to the c/unix
// convention, and not work generally.
//buf[length] = 0; // new
while( *p ) {
assert( p < (buf+length) );
if ( *p == 0xa ) {
// Newline character. No special rules for this. Append all the characters
// since the last string, and include the newline.
data.append( lastPos, (p-lastPos+1) ); // append, include the newline
++p; // move past the newline
lastPos = p; // and point to the new buffer (may be 0)
assert( p <= (buf+length) );
}
else if ( *p == 0xd ) {
// Carriage return. Append what we have so far, then
// handle moving forward in the buffer.
if ( (p-lastPos) > 0 ) {
data.append( lastPos, p-lastPos ); // do not add the CR
}
data += (char)0xa; // a proper newline
if ( *(p+1) == 0xa ) {
// Carriage return - new line sequence
p += 2;
lastPos = p;
assert( p <= (buf+length) );
}
else {
// it was followed by something else...that is presumably characters again.
++p;
lastPos = p;
assert( p <= (buf+length) );
}
}
else {
++p;
}
}
// Handle any left over characters.
if ( p-lastPos ) {
data.append( lastPos, p-lastPos );
}
Parse( data.c_str(), 0, encoding );
if ( Error() )
return false;
else
return true;
}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
sometimes it can be useful to include XML data as a static string in a project.
as far as i could see there is no way to load data this way...
altough i'm new to TinyXml, it was fairly easy to add that functionalitiy.
i've just split up the LoadFile function, that's all. there was no additional code needed.
the name LoadFile might be unsuitable though. it's a quick hack anyway,
but might be of interest for further versions, maybe, so i'll post the code here:
// tinyxml.h:1420
bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
bool LoadFile( const char * buf, long length, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); // new
// tinyxml.cpp:973
bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
{
if ( !file )
{
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
// Get the file size, so we can pre-allocate the string. HUGE speed impact.
long length = 0;
fseek( file, 0, SEEK_END );
length = ftell( file );
fseek( file, 0, SEEK_SET );
// Strange case, but good to handle up front.
if ( length <= 0 )
{
SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
// If we have a file, assume it is all one big XML file, and read it in.
// The document parser may decide the document ends sooner than the entire file, however.
TIXML_STRING data;
data.reserve( length );
// Subtle bug here. TinyXml did use fgets. But from the XML spec:
// 2.11 End-of-Line Handling
// <snip>
// <quote>
// ...the XML processor MUST behave as if it normalized all line breaks in external
// parsed entities (including the document entity) on input, before parsing, by translating
// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
// a single #xA character.
// </quote>
//
// It is not clear fgets does that, and certainly isn't clear it works cross platform.
// Generally, you expect fgets to translate from the convention of the OS to the c/unix
// convention, and not work generally.
/*
while( fgets( buf, sizeof(buf), file ) )
{
data += buf;
}
*/
char* buf = new char[ length+1 ];
buf[0] = 0;
if ( fread( buf, length, 1, file ) != 1 ) {
delete [] buf;
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
LoadFile( buf, length, encoding );
delete [] buf;
buf = 0;
if( Error() )
return false;
else
return true;
}
bool TiXmlDocument::LoadFile( const char *buf, long length, TiXmlEncoding encoding )
{
// Delete the existing data:
Clear();
location.Clear();
// Strange case, but good to handle up front.
if ( length <= 0 )
{
SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
// If we have a file, assume it is all one big XML file, and read it in.
// The document parser may decide the document ends sooner than the entire file, however.
TIXML_STRING data;
data.reserve( length );
// Subtle bug here. TinyXml did use fgets. But from the XML spec:
// 2.11 End-of-Line Handling
// <snip>
// <quote>
// ...the XML processor MUST behave as if it normalized all line breaks in external
// parsed entities (including the document entity) on input, before parsing, by translating
// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
// a single #xA character.
// </quote>
//
// It is not clear fgets does that, and certainly isn't clear it works cross platform.
// Generally, you expect fgets to translate from the convention of the OS to the c/unix
// convention, and not work generally.
/*
while( fgets( buf, sizeof(buf), file ) )
{
data += buf;
}
*/
const char* lastPos = buf;
const char* p = buf;
//buf[length] = 0; // new
while( *p ) {
assert( p < (buf+length) );
if ( *p == 0xa ) {
// Newline character. No special rules for this. Append all the characters
// since the last string, and include the newline.
data.append( lastPos, (p-lastPos+1) ); // append, include the newline
++p; // move past the newline
lastPos = p; // and point to the new buffer (may be 0)
assert( p <= (buf+length) );
}
else if ( *p == 0xd ) {
// Carriage return. Append what we have so far, then
// handle moving forward in the buffer.
if ( (p-lastPos) > 0 ) {
data.append( lastPos, p-lastPos ); // do not add the CR
}
data += (char)0xa; // a proper newline
if ( *(p+1) == 0xa ) {
// Carriage return - new line sequence
p += 2;
lastPos = p;
assert( p <= (buf+length) );
}
else {
// it was followed by something else...that is presumably characters again.
++p;
lastPos = p;
assert( p <= (buf+length) );
}
}
else {
++p;
}
}
// Handle any left over characters.
if ( p-lastPos ) {
data.append( lastPos, p-lastPos );
}
Parse( data.c_str(), 0, encoding );
if ( Error() )
return false;
else
return true;
}
...
// tinyxml.cpp : 1082
//buf[length] = 0;
const char *end = buf+length;
while( *p && p < end ) {
//assert( p < (buf+length) );
Just use TiXmlDocument::parse(), like
TiXmlDocument d;
d.parse("<Greeting>Hello there</Greeting>");
...
Ellers
thanks, you're right :)