• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/xml/TinyXmlNode.cpp

00001 /*
00002  *  Much of this code is extracted from the tinyxml project, attributed below.
00003  */
00004 /*
00005 www.sourceforge.net/projects/tinyxml
00006 Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
00007 
00008 This software is provided 'as-is', without any express or implied
00009 warranty. In no event will the authors be held liable for any
00010 damages arising from the use of this software.
00011 
00012 Permission is granted to anyone to use this software for any
00013 purpose, including commercial applications, and to alter it and
00014 redistribute it freely, subject to the following restrictions:
00015 
00016 1. The origin of this software must not be misrepresented; you must
00017 not claim that you wrote the original software. If you use this
00018 software in a product, an acknowledgment in the product documentation
00019 would be appreciated but is not required.
00020 
00021 2. Altered source versions must be plainly marked as such, and
00022 must not be misrepresented as being the original software.
00023 
00024 3. This notice may not be removed or altered from any source
00025 distribution.
00026 */
00027 
00028 #include <spl/xml/XmlAttribute.h>
00029 #include <spl/xml/XmlComment.h>
00030 #include <spl/xml/XmlDeclaration.h>
00031 #include <spl/xml/XmlDocument.h>
00032 #include <spl/xml/XmlElement.h>
00033 #include <spl/xml/XmlNode.h>
00034 #include <spl/xml/XmlText.h>
00035 #include <spl/xml/XmlUnknown.h>
00036 #include <spl/xml/xpath/XPath.h>
00037 
00038 XmlNode::XmlNode( XmlNodeType _type )
00039 : m_value(), m_type(_type), m_prev(), m_next(), m_firstChild(), m_lastChild(), m_parent(NULL)
00040 {
00041 }
00042 
00043 XmlNode::~XmlNode()
00044 {
00045         Clear();
00046         m_self.Clear();
00047 }
00048 
00049 void XmlNode::CopyTo( XmlNode& target ) const
00050 {
00051         target.SetValue(m_value.ToString());
00052 }
00053 
00054 void XmlNode::Clear()
00055 {
00056         XmlNodePtr node = m_firstChild;
00057         XmlNodePtr temp;
00058 
00059         while ( node.IsNotNull() )
00060         {
00061                 node.ValidateMem();
00062                 temp = node->m_next;
00063                 node->Clear();
00064                 node = temp;
00065         }
00066 
00067         m_next.Release();
00068         m_prev.Release();
00069         m_firstChild.Release();
00070         m_lastChild.Release();
00071 
00072         m_parent = NULL;
00073 }
00074 
00075 XmlNodeListPtr XmlNode::ChildNodes() const
00076 {
00077         XmlNodeListPtr nodes(new XmlNodeList());
00078         XmlNodePtr node(m_firstChild);
00079         
00080         if (node.IsNull())
00081         {
00082                 return nodes;
00083         }
00084         
00085         for ( ; node.IsNotNull(); node = node->NextSibling() )
00086         {
00087                 nodes->Add(node);
00088         }
00089         
00090         return nodes;
00091 }
00092 
00093 void XmlNode::AppendChild( XmlNodePtr node )
00094 {
00095         node.ValidateMem();
00096 
00097         ASSERT( node->m_parent == NULL || node->m_parent == this );
00098 
00099         if ( node->NodeType() == XmlNode::DOCUMENT )
00100         {
00101                 throw new XmlException("Cannot have a document as as child", -1, -1);
00102         }
00103 
00104         ASSERT( node->GetDocument().IsNull() || node->GetDocument().Get() == this->GetDocument().Get() );
00105 
00106         node->m_parent = this;
00107 
00108         node->m_prev = LastChild();
00109         node->m_next.Release();
00110 
00111         if ( m_lastChild.IsNotNull() )
00112         {
00113                 m_lastChild->m_next = node;
00114         }
00115         else
00116         {
00117                 m_firstChild = node;                    // it was an empty list.
00118         }
00119 
00120         m_lastChild = node;
00121 }
00122 
00123 void XmlNode::InsertBefore( XmlNodePtr beforeThis, XmlNodePtr addThis )
00124 {       
00125         if ( beforeThis.IsNull() || beforeThis->m_parent != this ) 
00126         {
00127                 throw  new XmlException("InsertBeforeChild: Argument is not a child of this node", -1, -1);
00128         }
00129         if ( addThis->NodeType() == XmlNode::DOCUMENT )
00130         {
00131                 throw new XmlException("InsertBeforeChild: Cannot add document childern", -1, -1);
00132         }
00133 
00134         addThis->m_parent = this;
00135 
00136         addThis->m_next = beforeThis;
00137         addThis->m_prev = beforeThis->m_prev;
00138         if ( beforeThis->m_prev.IsNotNull() )
00139         {
00140                 beforeThis->m_prev->m_next = addThis;
00141         }
00142         else
00143         {
00144                 ASSERT( m_firstChild.Get() == beforeThis.Get() );
00145                 m_firstChild = addThis;
00146         }
00147         beforeThis->m_prev = addThis;
00148 }
00149 
00150 void XmlNode::InsertAfter( XmlNodePtr afterThis, XmlNodePtr addThis )
00151 {
00152         if ( afterThis.IsNull() || afterThis->m_parent != this ) 
00153         {
00154                 throw new XmlException("InsertAfterChild: Argument is not a child of this node", -1, -1);
00155         }
00156         if ( addThis->NodeType() == XmlNode::DOCUMENT )
00157         {
00158                 throw new XmlException("InsertAfterChild: Cannot add document childern", -1, -1);
00159         }
00160 
00161         addThis->m_parent = this;
00162 
00163         addThis->m_prev = afterThis;
00164         addThis->m_next = afterThis->m_next;
00165         if ( afterThis->m_next.IsNotNull() )
00166         {
00167                 afterThis->m_next->m_prev = addThis;
00168         }
00169         else
00170         {
00171                 ASSERT( m_lastChild.Get() == afterThis.Get() );
00172                 m_lastChild = addThis;
00173         }
00174         afterThis->m_next = addThis;
00175 }
00176 
00177 void XmlNode::ReplaceChild( XmlNodePtr replaceThis, XmlNodePtr withThis )
00178 {
00179         replaceThis.ValidateMem();
00180 
00181         if ( replaceThis->m_parent != this )
00182         {
00183                 throw new XmlException("ReplaceChild: argument is not a child of this node", -1, -1);
00184         }
00185 
00186         withThis->m_next = replaceThis->m_next;
00187         withThis->m_prev = replaceThis->m_prev;
00188 
00189         if ( replaceThis->m_next.IsNotNull() )
00190         {
00191                 replaceThis->m_next->m_prev = withThis;
00192         }
00193         else
00194         {
00195                 m_lastChild = withThis;
00196         }
00197 
00198         if ( replaceThis->m_prev.IsNotNull() )
00199         {
00200                 replaceThis->m_prev->m_next = withThis;
00201         }
00202         else
00203         {
00204                 m_firstChild = withThis;
00205         }
00206 
00207         withThis->m_parent = this;
00208 }
00209 
00210 bool XmlNode::RemoveChild( XmlNodePtr removeThis )
00211 {
00212         removeThis.ValidateMem();
00213 
00214         if ( removeThis->m_parent != this )
00215         {       
00216                 throw new XmlException("RemoveChild: Argument is not a child of this node", -1, -1);
00217         }
00218 
00219         if ( removeThis->m_next.IsNotNull() )
00220         {
00221                 removeThis->m_next->m_prev = removeThis->m_prev;
00222         }
00223         else
00224         {
00225                 m_lastChild = removeThis->m_prev;
00226         }
00227 
00228         if ( removeThis->m_prev.IsNotNull() )
00229         {
00230                 removeThis->m_prev->m_next = removeThis->m_next;
00231         }
00232         else
00233         {
00234                 m_firstChild = removeThis->m_next;
00235         }
00236 
00237         return true;
00238 }
00239 
00240 XmlNodePtr XmlNode::FirstChild( const String& _value ) const
00241 {
00242         if (m_firstChild.IsNull())
00243         {
00244                 return XmlNodePtr();
00245         }
00246         XmlNodePtr node;
00247         for ( node = m_firstChild; node.IsNotNull(); node = node->m_next )
00248         {
00249                 if ( node->Name().Equals(_value) )
00250                 {
00251                         return node;
00252                 }
00253         }
00254         return XmlNodePtr();
00255 }
00256 
00257 XmlNodePtr XmlNode::LastChild( const String& _value ) const
00258 {
00259         if (m_lastChild.IsNull())
00260         {
00261                 return XmlNodePtr();
00262         }
00263         XmlNodePtr node;
00264         for ( node = m_lastChild; node.IsNotNull(); node = node->m_prev )
00265         {
00266                 if ( node->Name().Equals(_value) )
00267                 {
00268                         return node;
00269                 }
00270         }
00271         return XmlNodePtr();
00272 }
00273 
00274 XmlNodePtr XmlNode::Child( int count ) const
00275 {
00276         int i;
00277         XmlNodePtr child = FirstChild();
00278         for (   i=0;
00279                         child.IsNotNull() && i< count;
00280                         child = child->NextSibling(), ++i )
00281         {
00282                 // nothing
00283         }
00284         return child;
00285 }
00286 
00287 RefCountPtr<XmlNodeList> XmlNode::Decendants()
00288 {
00289         RefCountPtr<XmlNodeList> list(new XmlNodeList());
00290         
00291         for(XmlNode::Iterator iter(Begin()); iter.Next(); )
00292         {
00293                 list->Add(iter.Current());
00294         }
00295         return list;
00296 }
00297 
00298 XmlNodePtr XmlNode::NextSibling( const String& _value ) 
00299 {
00300         XmlNodePtr node;
00301         for ( node = m_next; node.IsNotNull(); node = node->m_next )
00302         {
00303                 if ( node->Name().Equals(_value) )
00304                 {
00305                         return node;
00306                 }
00307         }
00308         return XmlNodePtr();
00309 }
00310 
00311 XmlNodePtr XmlNode::PreviousSibling( const String& _value )
00312 {
00313         XmlNodePtr node;
00314         for ( node = m_prev; node.IsNotNull(); node = node->m_prev )
00315         {
00316                 if ( node->Name().Equals(_value) )
00317                 {
00318                         return node;
00319                 }
00320         }
00321         return XmlNodePtr();
00322 }
00323 
00324 XmlElementPtr XmlNode::FirstChildElement()
00325 {
00326         XmlNodePtr node;
00327 
00328         for ( node = FirstChild(); node.IsNotNull(); node = node->NextSibling() )
00329         {
00330                 if ( node->IsElement() )
00331                 {
00332                         return node->ToElement();
00333                 }
00334         }
00335         return XmlNodePtr();
00336 }
00337 
00338 XmlElementPtr XmlNode::FirstChildElement( const String& _value )
00339 {
00340         XmlNodePtr node;
00341 
00342         for (node = FirstChild( _value ); node.IsNotNull();     node = node->NextSibling( _value ) )
00343         {
00344                 if ( node->IsElement() )
00345                 {
00346                         return node->ToElement();
00347                 }
00348         }
00349         return XmlNodePtr();
00350 }
00351 
00352 XmlElementPtr XmlNode::NextSiblingElement()
00353 {
00354         XmlNodePtr node;
00355 
00356         for (node = NextSibling(); node.IsNotNull(); node = node->NextSibling() )
00357         {
00358                 if ( node->IsElement() )
00359                 {
00360                         return node->ToElement();
00361                 }
00362         }
00363         return XmlNodePtr();
00364 }
00365 
00366 XmlElementPtr XmlNode::NextSiblingElement( const String& _value )
00367 {
00368         XmlNodePtr node;
00369 
00370         for (node = NextSibling( _value ); node.IsNotNull(); node = node->NextSibling( _value ) )
00371         {
00372                 if ( node->IsElement() )
00373                 {
00374                         return node->ToElement();
00375                 }
00376         }
00377         return XmlNodePtr();
00378 }
00379 
00380 XmlDocumentPtr XmlNode::GetDocument()
00381 {
00382         XmlNode* node;
00383 
00384         for( node = this; NULL != node; node = node->m_parent )
00385         {
00386                 ASSERT_PTR(node);
00387 #ifdef DEBUG2
00388                 node->ValidateMem();
00389 #endif
00390                 if ( node->IsDocument() )
00391                 {
00392                         return (XmlNodePtr)node->m_self;
00393                 }
00394         }
00395         return XmlDocumentPtr();
00396 }
00397 
00398 StringPtr XmlNode::InnerText() const
00399 {
00400         return m_value.ToString();
00401 }
00402 
00403 StringPtr XmlNode::InnerXml() const
00404 {
00405         return StringPtr(new String());
00406 }
00407 
00408 XmlNodeListPtr XmlNode::SelectNodes(const String& xpath)
00409 {
00410         XPath xp(xpath);
00411         return xp.SelectNodes(m_self);
00412 }
00413 
00414 XmlNodePtr XmlNode::SelectSingleNode(const String& xpath)
00415 {
00416         XPath xp(xpath);
00417         return xp.SelectSingleNode(m_self);
00418 }
00419 
00420 XmlDocumentPtr    XmlNode::ToDocument()    const { return XmlNodePtr(); } 
00421 XmlElementPtr     XmlNode::ToElement()     const { return XmlNodePtr(); } 
00422 XmlCommentPtr     XmlNode::ToComment()     const { return XmlNodePtr(); } 
00423 XmlUnknownPtr     XmlNode::ToUnknown()     const { return XmlNodePtr(); } 
00424 XmlTextPtr        XmlNode::ToText()        const { return XmlNodePtr(); } 
00425 XmlDeclarationPtr XmlNode::ToDeclaration() const { return XmlNodePtr(); } 
00426 
00427 #ifdef DEBUG
00428 void XmlNode::ValidateMem() const
00429 {
00430         m_value.ValidateMem();
00431         if (NULL != m_parent)
00432         {
00433                 ASSERT_PTR(m_parent);
00434         }
00435         m_firstChild.ValidateMem();
00436 
00437 #ifdef DEBUG2
00438         XmlNodePtr node = m_firstChild;
00439         while ( node.IsNotNull() )
00440         {
00441                 node.ValidateMem();
00442                 node = node->m_next;
00443         }
00444 #else
00445         XmlNode* node = m_firstChild.Get();
00446         while ( NULL != node )
00447         {
00448                 node->ValidateMem();
00449                 node = node->m_next.Get();
00450         }
00451 #endif
00452 }
00453 
00454 void XmlNode::CheckMem() const
00455 {
00456         m_value.CheckMem();
00457 
00458         XmlNodePtr node = m_firstChild;
00459         while ( node.IsNotNull() )
00460         {
00461                 node.CheckMem();
00462                 node = node->m_next;
00463         }
00464 }
00465 #endif
00466 
00467 XmlNode::Iterator::Iterator(XmlNodePtr root)    //< root is not iterated
00468 : m_stack(), m_current()
00469 {
00470         XmlNodeListPtr childern(root->ChildNodes());
00471         for (int x = 0; x < childern->Count(); x++)
00472         {
00473                 m_stack.Add(childern->Item(x));
00474         }
00475 }
00476 
00477 XmlNode::Iterator::Iterator(const XmlNode::Iterator& iter)
00478 : m_stack(iter.m_stack), m_current(iter.m_current)
00479 {
00480 }
00481 
00482 XmlNode::Iterator::~Iterator()
00483 {
00484 }
00485 
00486 XmlNode::Iterator& XmlNode::Iterator::operator =(const XmlNode::Iterator iter)
00487 {
00488         m_stack = iter.m_stack;
00489         m_current = iter.m_current;
00490         
00491         return *this;
00492 }
00493 
00494 bool XmlNode::Iterator::Next()
00495 {
00496         if (m_stack.Count() == 0)
00497         {
00498                 return false;
00499         }
00500         
00501         m_current = m_stack.Tail();
00502         m_stack.RemoveTail();
00503         
00504         XmlNodeListPtr childern(m_current->ChildNodes());
00505         for (int x = 0; x < childern->Count(); x++)
00506         {
00507                 m_stack.Add(childern->Item(x));
00508         }
00509 
00510         return true;
00511 }
00512 
00513 bool XmlNode::Iterator::Prev( )
00514 {
00515         throw new NotImplementedException();
00516 }
00517 
00518 XmlNodePtr XmlNode::Iterator::Current()
00519 {
00520         return m_current;       
00521 }
00522 
00523 XmlNodePtr& XmlNode::Iterator::CurrentRef()
00524 {
00525         return m_current;
00526 }
00527 
00528 XmlUnknown::~XmlUnknown() 
00529 {
00530 }
00531 
00532 XmlUnknownPtr XmlUnknown::ToUnknown() const 
00533 { 
00534         return (XmlNodePtr)m_self; 
00535 } 
00536