# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

i_xml.cpp

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