i_xml.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "stdmisc.h"
00025 
00026 #include "nel/misc/i_xml.h"
00027 #include "nel/misc/sstring.h"
00028 
00029 #ifndef NL_DONT_USE_EXTERNAL_CODE
00030 
00031 // Include from libxml2
00032 #include <libxml/xmlerror.h>
00033 
00034 using namespace std;
00035 
00036 #define NLMISC_READ_BUFFER_SIZE 1024
00037 
00038 namespace NLMISC
00039 {
00040 
00041 // *********************************************************
00042 
00043 const char SEPARATOR = ' ';
00044 
00045 // ***************************************************************************
00046 
00047 #define readnumber(dest,thetype,digits,convfunc) \
00048     string number_as_string; \
00049     serialSeparatedBufferIn( number_as_string ); \
00050     dest = (thetype)convfunc( number_as_string.c_str() );
00051 
00052 // ***************************************************************************
00053 
00054 inline void CIXml::flushContentString ()
00055 {
00056     // String size
00057     _ContentString.erase ();
00058 
00059     // Reset
00060     _ContentStringIndex = 0;
00061 }
00062 
00063 // ***************************************************************************
00064 
00065 CIXml::CIXml () : IStream (true /* Input mode */)
00066 {
00067     // Not initialized
00068     _Parser = NULL;
00069     _CurrentElement = NULL;
00070     _CurrentNode = NULL;
00071     _PushBegin = false;
00072     _AttribPresent = false;
00073     _ErrorString = "";
00074     _TryBinaryMode = false;
00075     _BinaryStream = NULL;
00076 }
00077 
00078 // ***************************************************************************
00079 
00080 CIXml::CIXml (bool tryBinaryMode) : IStream (true /* Input mode */)
00081 {
00082     // Not initialized
00083     _Parser = NULL;
00084     _CurrentElement = NULL;
00085     _CurrentNode = NULL;
00086     _PushBegin = false;
00087     _AttribPresent = false;
00088     _ErrorString = "";
00089     _TryBinaryMode = tryBinaryMode;
00090     _BinaryStream = NULL;
00091 }
00092 
00093 // ***************************************************************************
00094 
00095 CIXml::~CIXml ()
00096 {
00097     // Release
00098     release ();
00099 }
00100 
00101 // ***************************************************************************
00102 
00103 void CIXml::release ()
00104 {
00105     // Release the parser
00106     if (_Parser)
00107     {
00108         // Free it
00109         xmlClearParserCtxt (_Parser);
00110         xmlFreeParserCtxt (_Parser);
00111         xmlCleanupParser ();
00112 
00113         _Parser = NULL;
00114     }
00115 
00116     // Not initialized
00117     _Parser = NULL;
00118     _CurrentElement = NULL;
00119     _CurrentNode = NULL;
00120     _PushBegin = false;
00121     _AttribPresent = false;
00122     _ErrorString = "";
00123 
00124     resetPtrTable();
00125 }
00126 
00127 // ***************************************************************************
00128 
00129 void xmlGenericErrorFuncRead (void *ctx, const char *msg, ...)
00130 {
00131     // Get the error string
00132     string str;
00133     NLMISC_CONVERT_VARGS (str, msg, NLMISC::MaxCStringSize);
00134     ((CIXml*)ctx)->_ErrorString += str;
00135 }
00136 
00137 // ***************************************************************************
00138 
00139 bool CIXml::init (IStream &stream)
00140 {
00141     // Release
00142     release ();
00143 
00144     xmlInitParser();
00145 
00146     // Default : XML mode
00147     _BinaryStream = NULL;
00148 
00149     // Input stream ?
00150     if (stream.isReading())
00151     {
00152         // Set XML mode
00153         setXMLMode (true);
00154 
00155         // Get current position
00156         sint32 pos = stream.getPos ();
00157 
00158         // Go to end
00159         bool seekGood = stream.seek (0, end);
00160         nlassert (seekGood);
00161 
00162         // Get input stream length
00163         sint32 length = stream.getPos () - pos;
00164 
00165         // Go to start
00166         stream.seek (pos, begin);
00167 
00168         // The read buffer
00169         char buffer[NLMISC_READ_BUFFER_SIZE];
00170 
00171         // Fill the buffer
00172         stream.serialBuffer ((uint8*)buffer, 4);
00173         length -= 4;
00174 
00175         // Try binary mode
00176         if (_TryBinaryMode)
00177         {
00178             string header;
00179             header.resize(4);
00180             header[0] = buffer[0];
00181             header[1] = buffer[1];
00182             header[2] = buffer[2];
00183             header[3] = buffer[3];
00184             toLower(header);
00185 
00186             // Does it a xml stream ?
00187             if (header != "<?xm")
00188             {
00189                 // NO ! Go in binary mode
00190                 _BinaryStream = &stream;
00191 
00192                 // Seek back to the start
00193                 stream.seek (pos, begin);
00194 
00195                 // Done
00196                 return true;
00197             }
00198         }
00199 
00200         // Set error handler
00201         _ErrorString = "";
00202         xmlSetGenericErrorFunc  (this, xmlGenericErrorFuncRead);
00203 
00204         // Ask to get debug info
00205         xmlLineNumbersDefault(1);
00206 
00207         // The parser context
00208         _Parser = xmlCreatePushParserCtxt(NULL, NULL, buffer, 4, NULL);
00209         nlassert (_Parser);
00210 
00211         // For all the file
00212         while (length>=NLMISC_READ_BUFFER_SIZE)
00213         {
00214             // Fill the buffer
00215             stream.serialBuffer ((uint8*)buffer, NLMISC_READ_BUFFER_SIZE);
00216 
00217             // Read a buffer
00218             int res = xmlParseChunk(_Parser, buffer, NLMISC_READ_BUFFER_SIZE, 0);
00219 
00220             // Error code ?
00221             if (res)
00222             {
00223                 throw EXmlParsingError (_ErrorString);
00224             }
00225 
00226             // Length left
00227             length -= NLMISC_READ_BUFFER_SIZE;
00228         }
00229 
00230         // Fill the buffer
00231         stream.serialBuffer ((uint8*)buffer, length);
00232 
00233         // Parse the last buffer
00234         int res = xmlParseChunk(_Parser, buffer, length, 1);
00235 
00236         // Error code ?
00237         if (res)
00238         {
00239             throw EXmlParsingError (_ErrorString);
00240         }
00241 
00242         // Ok
00243         return true;
00244     }
00245     else
00246     {
00247         nlwarning ("XML: The stream is not an input stream.");
00248     }
00249 
00250     // Error
00251     return false;
00252 }
00253 
00254 // ***************************************************************************
00255 
00256 void CIXml::serialSeparatedBufferIn ( string &value, bool checkSeparator )
00257 {
00258     nlassert( isReading() );
00259 
00260     // Output stream has been initialized ?
00261     if ( _Parser )
00262     {
00263         // Current node presents ?
00264         if (_CurrentElement)
00265         {
00266             // Write a push attribute ?
00267             if (_PushBegin)
00268             {
00269                 // Current attrib is set ?
00270                 if (_AttribPresent)
00271                 {
00272                     // Should have a current element
00273                     nlassert (_CurrentElement);
00274 
00275                     // Get the attribute
00276                     xmlChar *attributeValue = xmlGetProp (_CurrentElement, (const xmlChar*)_AttribName.c_str());
00277 
00278                     // Attribute is here ?
00279                     if (attributeValue)
00280                     {
00281                         // Copy the value
00282                         value = (const char*)attributeValue;
00283 
00284                         // Delete the value
00285                         xmlFree ((void*)attributeValue);
00286                     }
00287                     else
00288                     {
00289                         // Node name must not be NULL
00290                         nlassert (_CurrentElement->name);
00291 
00292                         // Make an error message
00293                         char tmp[512];
00294                         smprintf (tmp, 512, "NeL XML Syntax error in block line %d\nAttribute \"%s\" is missing in node \"%s\"",
00295                             (int)_CurrentElement->line, _AttribName.c_str(), _CurrentElement->name);
00296                         throw EXmlParsingError (tmp);
00297                     }
00298 
00299                     // The attribute has been used
00300                     _AttribPresent = false;
00301                 }
00302                 else
00303                 {
00304                     // * Error, the stream don't use XML streaming properly
00305                     // * You must take care of this in your last serial call:
00306                     // * - Between xmlPushBegin() and xmlPushEnd(), before each serial, you must set the attribute name with xmlSetAttrib.
00307                     // * - Between xmlPushBegin() and xmlPushEnd(), you must serial only basic objects (numbers and strings).
00308                     nlerror ( "Error, the stream don't use XML streaming properly" );
00309                 }
00310             }
00311             else
00312             {
00313                 // Content length
00314                 uint length = _ContentString.length();
00315 
00316                 // String empty ?
00317                 if (length==0)
00318                 {
00319                     // Try to open the node
00320                     do
00321                     {
00322                         // If no more node, empty string
00323                         if (_CurrentNode == NULL)
00324                         {
00325                             value = "";
00326                             _ContentStringIndex = 0;
00327                             _ContentString.erase ();
00328                             return;
00329                         }
00330 
00331                         // Node with the good name
00332                         if (_CurrentNode->type == XML_TEXT_NODE)
00333                         {
00334                             // Stop searching
00335                             break;
00336                         }
00337                         else
00338                             // Get next
00339                             _CurrentNode = _CurrentNode->next;
00340                     }
00341                     while (_CurrentNode);
00342 
00343                     // Not found ?
00344                     if (_CurrentNode != NULL)
00345                     {
00346                         // Read the content
00347                         const char *content = (const char*)xmlNodeGetContent (_CurrentNode);
00348                         if (content)
00349                         {
00350                             _ContentString = content;
00351 
00352                             // Delete the value
00353                             xmlFree ((void*)content);
00354                         }
00355                         else
00356                             _ContentString.erase ();
00357 
00358                         // Set the current index
00359                         _ContentStringIndex = 0;
00360 
00361                         // New length
00362                         length = _ContentString.length();
00363                     }
00364                 }
00365 
00366                 // Keyword in the buffer ?
00367                 if (_ContentStringIndex < length)
00368                 {
00369                     // First index
00370                     uint first = _ContentStringIndex;
00371 
00372                     // Have to take care of separators ?
00373                     if (checkSeparator)
00374                     {
00375                         // Scan to the end
00376                         while (_ContentStringIndex < length)
00377                         {
00378                             // Not a separator ?
00379                             if ( (_ContentString[_ContentStringIndex]==SEPARATOR) || (_ContentString[_ContentStringIndex]=='\n') )
00380                             {
00381                                 _ContentStringIndex++;
00382                                 break;
00383                             }
00384 
00385                             // Next char
00386                             _ContentStringIndex++;
00387                         }
00388                     }
00389                     else
00390                     {
00391                         // Copy all the string
00392                         _ContentStringIndex = length;
00393                     }
00394 
00395                     // Make a string
00396                     value.assign (_ContentString, first, _ContentStringIndex-first);
00397                 }
00398                 else
00399                 {
00400                     // Should have a name
00401                     nlassert (_CurrentElement->name);
00402 
00403                     // Make an error message
00404                     char tmp[512];
00405                     smprintf (tmp, 512, "NeL XML Syntax error in block line %d \nMissing keywords in text child node in the node %s",
00406                         (int)_CurrentElement->line, _CurrentElement->name);
00407                     throw EXmlParsingError (tmp);
00408                 }
00409             }
00410         }
00411         else
00412         {
00413             // * Error, no current node present.
00414             // * Check that your serial is initialy made between a xmlPushBegin and xmlPushEnd calls.
00415             nlerror ( "Error, the stream don't use XML streaming properly" );
00416         }
00417     }
00418     else
00419     {
00420         nlerror ( "Output stream has not been initialized" );
00421     }
00422 }
00423 
00424 // ***************************************************************************
00425 
00426 void CIXml::serial(uint8 &b)
00427 {
00428     if (_BinaryStream)
00429     {
00430         _BinaryStream->serial(b);
00431     }
00432     else
00433     {
00434         // Read the number
00435         readnumber( b, uint8, 3, atoi );
00436     }
00437 }
00438 
00439 // ***************************************************************************
00440 
00441 void CIXml::serial(sint8 &b)
00442 {
00443     if (_BinaryStream)
00444     {
00445         _BinaryStream->serial(b);
00446     }
00447     else
00448     {
00449         readnumber( b, sint8, 4, atoi );
00450     }
00451 }
00452 
00453 // ***************************************************************************
00454 
00455 void CIXml::serial(uint16 &b)
00456 {
00457     if (_BinaryStream)
00458     {
00459         _BinaryStream->serial(b);
00460     }
00461     else
00462     {
00463         readnumber( b, uint16, 5, atoi );
00464     }
00465 }
00466 
00467 // ***************************************************************************
00468 
00469 void CIXml::serial(sint16 &b)
00470 {
00471     if (_BinaryStream)
00472     {
00473         _BinaryStream->serial(b);
00474     }
00475     else
00476     {
00477         readnumber( b, sint16, 6, atoi );
00478     }
00479 }
00480 
00481 // ***************************************************************************
00482 
00483 inline uint32 atoui( const char *ident)
00484 {
00485     return (uint32) strtoul (ident, NULL, 10);
00486 }
00487 
00488 void CIXml::serial(uint32 &b)
00489 {
00490     if (_BinaryStream)
00491     {
00492         _BinaryStream->serial(b);
00493     }
00494     else
00495     {
00496         readnumber( b, uint32, 10, atoui );
00497     }
00498 }
00499 
00500 // ***************************************************************************
00501 
00502 void CIXml::serial(sint32 &b)
00503 {
00504     if (_BinaryStream)
00505     {
00506         _BinaryStream->serial(b);
00507     }
00508     else
00509     {
00510         readnumber( b, sint32, 11, atoi );
00511     }
00512 }
00513 
00514 // ***************************************************************************
00515 
00516 void CIXml::serial(uint64 &b)
00517 {
00518     if (_BinaryStream)
00519     {
00520         _BinaryStream->serial(b);
00521     }
00522     else
00523     {
00524         readnumber( b, uint64, 20, atoiInt64 );
00525     }
00526 }
00527 
00528 // ***************************************************************************
00529 
00530 void CIXml::serial(sint64 &b)
00531 {
00532     if (_BinaryStream)
00533     {
00534         _BinaryStream->serial(b);
00535     }
00536     else
00537     {
00538         readnumber( b, sint64, 20, atoiInt64 );
00539     }
00540 }
00541 
00542 // ***************************************************************************
00543 
00544 void CIXml::serial(float &b)
00545 {
00546     if (_BinaryStream)
00547     {
00548         _BinaryStream->serial(b);
00549     }
00550     else
00551     {
00552         readnumber( b, float, 128, atof );
00553     }
00554 }
00555 
00556 // ***************************************************************************
00557 
00558 void CIXml::serial(double &b)
00559 {
00560     if (_BinaryStream)
00561     {
00562         _BinaryStream->serial(b);
00563     }
00564     else
00565     {
00566         readnumber( b, double, 128, atof );
00567     }
00568 }
00569 
00570 // ***************************************************************************
00571 
00572 void CIXml::serial(bool &b)
00573 {
00574     if (_BinaryStream)
00575     {
00576         _BinaryStream->serial(b);
00577     }
00578     else
00579     {
00580         serialBit(b);
00581     }
00582 }
00583 
00584 // ***************************************************************************
00585 
00586 void CIXml::serialBit(bool &bit)
00587 {
00588     if (_BinaryStream)
00589     {
00590         _BinaryStream->serialBit(bit);
00591     }
00592     else
00593     {
00594         uint8 u;
00595         serial (u);
00596         bit = (u!=0);
00597     }
00598 }
00599 
00600 // ***************************************************************************
00601 
00602 #ifndef NL_OS_CYGWIN
00603 void CIXml::serial(char &b)
00604 {
00605     if (_BinaryStream)
00606     {
00607         _BinaryStream->serial(b);
00608     }
00609     else
00610     {
00611         string toto;
00612         serialSeparatedBufferIn ( toto );
00613 
00614         // Good value ?
00615         if (toto.length()!=1)
00616         {
00617             // Protect error
00618             if (_Parser)
00619             {
00620                 // Should have a name
00621                 nlassert (_CurrentElement->name);
00622 
00623                 // Make an error message
00624                 char tmp[512];
00625                 smprintf (tmp, 512, "NeL XML Syntax error in block line %d \nValue is not a char in the node named %s",
00626                     (int)_CurrentElement->line, _CurrentElement->name);
00627                 throw EXmlParsingError (tmp);
00628             }
00629             else
00630             {
00631                 nlerror ( "Output stream has not been initialized" );
00632             }
00633         }
00634         else
00635             b=toto[0];
00636     }
00637 }
00638 #endif // NL_OS_CYGWIN
00639 
00640 // ***************************************************************************
00641 
00642 void CIXml::serial(std::string &b)
00643 {
00644     nlassert( isReading() );
00645 
00646     if (_BinaryStream)
00647     {
00648         _BinaryStream->serial(b);
00649     }
00650     else
00651     {
00652         // Attibute ?
00653         if (_PushBegin)
00654         {
00655             // Only serial the string
00656             serialSeparatedBufferIn ( b, false );
00657         }
00658         else
00659         {
00660             // Open a string node
00661             xmlPush ("S");
00662 
00663             // Serial the string
00664             serialSeparatedBufferIn ( b, false );
00665 
00666             // Close the node
00667             xmlPop ();
00668         }
00669     }
00670 }
00671 
00672 // ***************************************************************************
00673 
00674 void CIXml::serial(ucstring &b)
00675 {
00676     nlassert( isReading() );
00677 
00678     if (_BinaryStream)
00679     {
00680         _BinaryStream->serial(b);
00681     }
00682     else
00683     {
00684         // Serial a simple string
00685         string tmp;
00686 
00687         // Serial this string
00688         serial (tmp);
00689 
00690         // Return a ucstring
00691         b.fromUtf8(tmp);
00692     }
00693 }
00694 
00695 // ***************************************************************************
00696 
00697 void CIXml::serialBuffer(uint8 *buf, uint len)
00698 {
00699     if (_BinaryStream)
00700     {
00701         _BinaryStream->serialBuffer(buf, len);
00702     }
00703     else
00704     {
00705         // Open a node
00706         xmlPush ("BUFFER");
00707 
00708         // Serialize the buffer
00709         for (uint i=0; i<len; i++)
00710         {
00711             xmlPush ("ELM");
00712 
00713             serial (buf[i]);
00714 
00715             xmlPop ();
00716         }
00717 
00718         // Close the node
00719         xmlPop ();
00720     }
00721 }
00722 
00723 // ***************************************************************************
00724 
00725 bool CIXml::xmlPushBeginInternal (const char *nodeName)
00726 {
00727     nlassert( isReading() );
00728 
00729     if (_BinaryStream)
00730     {
00731         return true;
00732     }
00733     else
00734     {
00735         // Check _Parser
00736         if ( _Parser )
00737         {
00738             // Can make a xmlPushBegin ?
00739             if ( ! _PushBegin )
00740             {
00741                 // Current node exist ?
00742                 if (_CurrentNode==NULL)
00743                 {
00744                     // Get the first node
00745                     _CurrentNode = xmlDocGetRootElement (_Parser->myDoc);
00746 
00747                     // Has a root node ?
00748                     if (_CurrentNode)
00749                     {
00750                         // Node name must not be NULL
00751                         nlassert (_CurrentNode->name);
00752 
00753                         // Node element with the good name ?
00754                         if ( (_CurrentNode->type != XML_ELEMENT_NODE) || ( (const char*)_CurrentNode->name != string(nodeName)) )
00755                         {
00756                             // Make an error message
00757                             char tmp[512];
00758                             smprintf (tmp, 512, "NeL XML Syntax error : root node has the wrong name : \"%s\" should have \"%s\"",
00759                                 _CurrentNode->name, nodeName);
00760                             throw EXmlParsingError (tmp);
00761                         }
00762                     }
00763                     else
00764                     {
00765                         // Make an error message
00766                         char tmp[512];
00767                         smprintf (tmp, 512, "NeL XML Syntax error : no root node found.");
00768                         throw EXmlParsingError (tmp);
00769                     }
00770                 }
00771 
00772                 // Try to open the node
00773                 do
00774                 {
00775                     // Node name must not be NULL
00776                     nlassert (_CurrentNode->name);
00777 
00778                     // Node with the good name
00779                     if ( (_CurrentNode->type == XML_ELEMENT_NODE) && ( (const char*)_CurrentNode->name == string(nodeName)) )
00780                     {
00781                         // Save current element
00782                         _CurrentElement = _CurrentNode;
00783 
00784                         // Stop searching
00785                         break;
00786                     }
00787                     else
00788                         // Get next
00789                         _CurrentNode = _CurrentNode->next;
00790                 }
00791                 while (_CurrentNode);
00792 
00793                 // Not found ?
00794                 if (_CurrentNode == NULL)
00795                 {
00796                     // Make an error message
00797                     char tmp[512];
00798                     smprintf (tmp, 512, "NeL XML Syntax error in block line %d \nCan't open the node named %s in node named %s",
00799                         (int)_CurrentElement->line, nodeName, _CurrentElement->name);
00800                     throw EXmlParsingError (tmp);
00801                 }
00802 
00803                 // Get first child
00804                 _CurrentNode = _CurrentNode->children;
00805 
00806                 // Push begun
00807                 _PushBegin = true;
00808 
00809                 // Flush current string
00810                 flushContentString ();
00811             }
00812             else
00813             {
00814                 nlerror ( "You must close your xmlPushBegin - xmlPushEnd before calling a new xmlPushBegin.");
00815                 return false;
00816             }
00817         }
00818         else
00819         {
00820             nlerror ( "Output stream has not been initialized.");
00821             return false;
00822         }
00823 
00824         // Ok
00825         return true;
00826     }
00827 }
00828 
00829 // ***************************************************************************
00830 
00831 bool CIXml::xmlPushEndInternal ()
00832 {
00833     nlassert( isReading() );
00834 
00835     if (_BinaryStream)
00836     {
00837         return true;
00838     }
00839     else
00840     {
00841         // Check _Parser
00842         if ( _Parser )
00843         {
00844             // Can make a xmlPushEnd ?
00845             if ( _PushBegin )
00846             {
00847                 // Push begun
00848                 _PushBegin = false;
00849             }
00850             else
00851             {
00852                 nlerror ( "You must call xmlPushBegin before calling xmlPushEnd.");
00853                 return false;
00854             }
00855         }
00856         else
00857         {
00858             nlerror ( "Output stream has not been initialized.");
00859             return false;
00860         }
00861 
00862         // Ok
00863         return true;
00864     }
00865 }
00866 
00867 // ***************************************************************************
00868 
00869 bool CIXml::xmlPopInternal ()
00870 {
00871     nlassert( isReading() );
00872 
00873     if (_BinaryStream)
00874     {
00875         return true;
00876     }
00877     else
00878     {
00879         // Check _Parser
00880         if ( _Parser )
00881         {
00882             // Not in the push mode ?
00883             if ( ! _PushBegin )
00884             {
00885                 // Some content to write ?
00886                 flushContentString ();
00887 
00888                 // Get parents
00889                 _CurrentNode = _CurrentElement;
00890                 _CurrentElement = _CurrentElement->parent;
00891                 _CurrentNode = _CurrentNode->next;
00892             }
00893             else
00894             {
00895                 nlerror ( "You must call xmlPop after xmlPushEnd.");
00896                 return false;
00897             }
00898         }
00899         else
00900         {
00901             nlerror ( "Output stream has not been initialized.");
00902             return false;
00903         }
00904 
00905         // Ok
00906         return true;
00907     }
00908 }
00909 
00910 // ***************************************************************************
00911 
00912 bool CIXml::xmlSetAttribInternal (const char *attribName)
00913 {
00914     nlassert( isReading() );
00915 
00916     if (_BinaryStream)
00917     {
00918         return true;
00919     }
00920     else
00921     {
00922         // Check _Parser
00923         if ( _Parser )
00924         {
00925             // Can make a xmlPushEnd ?
00926             if ( _PushBegin )
00927             {
00928                 // Set attribute name
00929                 _AttribName = attribName;
00930 
00931                 // Attribute name is present
00932                 _AttribPresent = true;
00933             }
00934             else
00935             {
00936                 nlerror ( "You must call xmlSetAttrib between xmlPushBegin and xmlPushEnd calls.");
00937                 return false;
00938             }
00939         }
00940         else
00941         {
00942             nlerror ( "Output stream has not been initialized.");
00943             return false;
00944         }
00945 
00946         // Ok
00947         return true;
00948     }
00949 }
00950 
00951 // ***************************************************************************
00952 
00953 bool CIXml::xmlBreakLineInternal ()
00954 {
00955     // Ok
00956     return true;
00957 }
00958 
00959 // ***************************************************************************
00960 
00961 bool CIXml::xmlCommentInternal (const char * /* comment */)
00962 {
00963     // Ok
00964     return true;
00965 }
00966 
00967 // ***************************************************************************
00968 
00969 xmlNodePtr CIXml::getFirstChildNode (xmlNodePtr parent, const char *childName)
00970 {
00971     xmlNodePtr child = parent->children;
00972     while (child)
00973     {
00974         if (strcmp ((const char*)child->name, childName) == 0)
00975             return child;
00976         child = child->next;
00977     }
00978     return NULL;
00979 }
00980 
00981 // ***************************************************************************
00982 
00983 xmlNodePtr CIXml::getNextChildNode (xmlNodePtr last, const char *childName)
00984 {
00985     last = last->next;
00986     while (last)
00987     {
00988         if (strcmp ((const char*)last->name, childName) == 0)
00989             return last;
00990         last = last->next;
00991     }
00992     return NULL;
00993 }
00994 
00995 // ***************************************************************************
00996 
00997 xmlNodePtr CIXml::getFirstChildNode (xmlNodePtr parent, xmlElementType type)
00998 {
00999     xmlNodePtr child = parent->children;
01000     while (child)
01001     {
01002         if (child->type == type)
01003             return child;
01004         child = child->next;
01005     }
01006     return NULL;
01007 }
01008 
01009 // ***************************************************************************
01010 
01011 xmlNodePtr CIXml::getNextChildNode (xmlNodePtr last, xmlElementType type)
01012 {
01013     last = last->next;
01014     while (last)
01015     {
01016         if (last->type == type)
01017             return last;
01018         last = last->next;
01019     }
01020     return NULL;
01021 }
01022 
01023 // ***************************************************************************
01024 
01025 uint CIXml::countChildren (xmlNodePtr node, const char *childName)
01026 {
01027     uint count=0;
01028     xmlNodePtr child = getFirstChildNode (node, childName);
01029     while (child)
01030     {
01031         count++;
01032         child = getNextChildNode (child, childName);
01033     }
01034     return count;
01035 }
01036 
01037 // ***************************************************************************
01038 
01039 uint CIXml::countChildren (xmlNodePtr node, xmlElementType type)
01040 {
01041     uint count=0;
01042     xmlNodePtr child = getFirstChildNode (node, type);
01043     while (child)
01044     {
01045         count++;
01046         child = getNextChildNode (child, type);
01047     }
01048     return count;
01049 }
01050 
01051 // ***************************************************************************
01052 
01053 xmlNodePtr CIXml::getRootNode () const
01054 {
01055     if (_Parser)
01056         if (_Parser->myDoc)
01057             return xmlDocGetRootElement (_Parser->myDoc);
01058     return NULL;
01059 }
01060 
01061 // ***************************************************************************
01062 
01063 bool CIXml::getPropertyString (std::string &result, xmlNodePtr node, const char *property)
01064 {
01065     // Get the value
01066     const char *value = (const char*)xmlGetProp (node, (xmlChar*)property);
01067     if (value)
01068     {
01069         // Active value
01070         result = value;
01071 
01072         // Delete the value
01073         xmlFree ((void*)value);
01074 
01075         // Found
01076         return true;
01077     }
01078     return false;
01079 }
01080 
01081 // ***************************************************************************
01082 
01083 int CIXml::getIntProperty(xmlNodePtr node, const char *property, int defaultValue)
01084 {
01085     CSString s;
01086     bool b;
01087 
01088     b=getPropertyString(s,node,property);
01089     if (b==false)
01090         return defaultValue;
01091 
01092     s=s.strip();
01093     int val=s.atoi();
01094     if (val==0 && s!="0")
01095     {
01096         nlwarning("bad integer value: %s",s.c_str());
01097         return defaultValue;
01098     }
01099 
01100     return val;
01101 }
01102 
01103 // ***************************************************************************
01104 
01105 double CIXml::getFloatProperty(xmlNodePtr node, const char *property, float defaultValue)
01106 {
01107     CSString s;
01108     bool b;
01109 
01110     b=getPropertyString(s,node,property);
01111     if (b==false)
01112         return defaultValue;
01113 
01114     return s.strip().atof();
01115 }
01116 
01117 // ***************************************************************************
01118 
01119 std::string CIXml::getStringProperty(xmlNodePtr node, const char *property, const std::string& defaultValue)
01120 {
01121     std::string s;
01122     bool b;
01123 
01124     b=getPropertyString(s,node,property);
01125     if (b==false)
01126         return defaultValue;
01127 
01128     return s;
01129 }
01130 
01131 // ***************************************************************************
01132 
01133 bool CIXml::getContentString (std::string &result, xmlNodePtr node)
01134 {
01135     const char *valueText = (const char*)xmlNodeGetContent (node);
01136     if (valueText)
01137     {
01138         result = valueText;
01139 
01140         // Delete the value
01141         xmlFree ((void*)valueText);
01142 
01143         // Found
01144         return true;
01145     }
01146     return false;
01147 }
01148 
01149 // ***************************************************************************
01150 
01151 } // NLMISC
01152 
01153 #endif // NL_DONT_USE_EXTERNAL_CODE

Generated on Thu Jan 7 08:26:34 2010 for NeL by  doxygen 1.6.1