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

src/xml/TinyXmlElement.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 #include <spl/io/Stream.h>
00028 #include <spl/text/StringBuffer.h>
00029 #include <spl/xml/XmlElement.h>
00030 #include <spl/xml/XmlText.h>
00031 
00032 void XmlElement::RemoveAttribute( const String& name )
00033 {
00034         if ( m_attribs.IsNull() )
00035         {
00036                 return;
00037         }
00038         XmlAttributePtr node = m_attribs->Find( name );
00039         if ( node.IsNotNull() )
00040         {
00041                 m_attribs->Remove( node );
00042         }
00043 }
00044 
00045 XmlElement::XmlElement (const String& _name)
00046 : XmlNode( XmlNode::ELEMENT ), m_name(_name), m_attribs()
00047 {
00048 }
00049 
00050 XmlElement::XmlElement( const XmlElement& copy)
00051 : XmlNode( XmlNode::ELEMENT ), m_name(copy.m_name), m_attribs()
00052 {
00053         copy.CopyTo( *this );
00054 }
00055 
00056 void XmlElement::operator=( const XmlElement& base )
00057 {
00058         ClearThis();
00059         base.CopyTo( *this );
00060         m_name = base.m_name;
00061 }
00062 
00063 XmlElement::~XmlElement()
00064 {
00065         ClearThis();
00066 }
00067 
00068 String XmlElement::Name() const
00069 {
00070         return m_name;
00071 }
00072 
00073 XmlElementPtr XmlElement::ChildElement( int count )
00074 {
00075         int i;
00076         XmlElementPtr child = FirstChildElement(  );
00077         for (   i=0;
00078                         child.IsNotNull() && i<count;
00079                         child = child->NextSiblingElement(  ), ++i )
00080         {
00081                 // nothing
00082         }
00083 
00084         return child;
00085 }
00086 
00087 XmlElementPtr XmlElement::ChildElement( const String& _value, int count )
00088 {
00089         int i;
00090         XmlElementPtr child = FirstChildElement( _value );
00091         for (   i=0;
00092                         child.IsNotNull() && i<count;
00093                         child = child->NextSiblingElement( _value ), ++i )
00094         {
00095                 // nothing
00096         }
00097         return child;
00098 }
00099 
00100 void XmlElement::ClearThis()
00101 {
00102         Clear();
00103         if ( m_attribs.IsNull() )
00104         {
00105                 return;
00106         }
00107         if( m_attribs.IsNotNull() )
00108         {
00109                 m_attribs->Clear();
00110         }
00111 }
00112 
00113 void XmlElement::SetAttribute( const String& cname, const String& cvalue )
00114 {
00115         if ( m_attribs.IsNull() )
00116         {
00117                 m_attribs = XmlAttributeCollectionPtr(new XmlAttributeCollection());
00118         }
00119 
00120         XmlAttributePtr node = m_attribs->Find( cname );
00121         if ( node.IsNotNull() )
00122         {
00123                 node->SetValue( cvalue );
00124                 return;
00125         }
00126 
00127         XmlAttributePtr attrib = new XmlAttribute( cname, cvalue );
00128         if ( attrib.IsNull() )
00129         {
00130                 extern const char** _xmlErrorStrings;
00131                 throw new XmlException( _xmlErrorStrings[TIXML_ENCODING_UNKNOWN], 0, 0 );
00132         }
00133         m_attribs->Add( attrib );
00134 }
00135 
00136 void XmlElement::WriteTo( TextWriter& writer ) const
00137 {
00138         writer.WriteFormat( "<%s", m_name.GetChars() );
00139 
00140         if ( m_attribs.IsNotNull() )
00141         {
00142                 for ( XmlAttributePtr attrib = m_attribs->First(); attrib.IsNotNull(); attrib = (XmlAttributePtr)attrib->NextSibling() )
00143                 {
00144                         attrib.ValidateMem();
00145                         writer.Write( " " );
00146                         attrib->WriteTo( writer );
00147                 }
00148         }
00149 
00150         // There are 3 different formatting approaches:
00151         // 1) An element without children is printed as a <foo /> node
00152         // 2) An element with only a text child is printed as <foo> text </foo>
00153         // 3) An element with children is printed on multiple lines.
00154         XmlNodePtr node;
00155         if ( m_firstChild.IsNull() )
00156         {
00157                 writer.Write( " />" );
00158         }
00159         else if ( m_firstChild.Get() == m_lastChild.Get() && m_firstChild->IsText() )
00160         {
00161                 writer.Write( ">" );
00162                 m_firstChild.ValidateMem();
00163                 m_firstChild->WriteTo( writer );
00164                 writer.WriteFormat( "</%s>", m_name.GetChars() );
00165         }
00166         else
00167         {
00168                 writer.Write( ">" );
00169 
00170                 for ( node = m_firstChild; node.IsNotNull(); node = node->NextSibling() )
00171                 {
00172                         m_firstChild.ValidateMem();
00173                         if ( node.Get() != m_firstChild.Get() )
00174                         {
00175                                 node->PreviousSibling()->ValidateMem();
00176                                 if ( /*NULL == node->ToText()  &&*/ ! node->PreviousSibling()->IsText() )
00177                                 {
00178                                         writer.Write( "\n" );
00179                                 }                               
00180                         }
00181                         node->WriteTo( writer );
00182                 }
00183                 writer.WriteFormat( "</%s>", m_name.GetChars() );
00184         }
00185 }
00186 
00187 void XmlElement::CopyTo( XmlElement& target ) const
00188 {
00189         // superclass:
00190         XmlNode::CopyTo( target );
00191 
00192         // Element class: 
00193         // Clone the attributes, then clone the children.
00194         if ( m_attribs.IsNotNull() )
00195         {
00196                 for ( int x = 0; x < m_attribs->Count(); x++ )
00197                 {
00198                         XmlAttributePtr attribute = (XmlAttributePtr)m_attribs->Item(x);
00199                         target.SetAttribute( attribute->Name(), *attribute->Value() );
00200                 }
00201         }
00202 
00203         if (m_firstChild.IsNotNull())
00204         {
00205                 XmlNodePtr node;
00206                 for ( node = m_firstChild; node.IsNotNull(); node = node->NextSibling() )
00207                 {
00208                         target.AppendChild( node->Clone() );
00209                 }
00210         }
00211 }
00212 
00213 XmlNodePtr XmlElement::Clone() const
00214 {
00215         XmlElementPtr clone = XmlElementPtr(new XmlElement( Name() ));
00216         XmlNodePtr xclone = (XmlNodePtr)clone;
00217         clone->m_self = xclone;
00218         CopyTo( *clone );
00219         return clone;
00220 }
00221 
00222 /*String XmlElement::GetText() const
00223 {
00224         const XmlNode* child = this->FirstChild();
00225         if ( child ) 
00226         {
00227                 const XmlText* childText = child->ToText();
00228                 if ( childText ) 
00229                 {
00230                         return childText->Value();
00231                 }
00232         }
00233         return String();
00234 }*/
00235 
00236 StringPtr XmlElement::InnerText() const
00237 {
00238         StringBuffer buf;
00239         XmlNodePtr child = FirstChild();
00240         while ( child.IsNotNull() ) 
00241         {
00242                 buf.Append( child->InnerText() );
00243                 child = child->NextSibling();
00244         }
00245         return buf.ToString();
00246 }
00247 
00248 StringPtr XmlElement::InnerXml() const
00249 {
00250         if ( m_firstChild.IsNull() )
00251         {
00252                 return StringPtr(new String());
00253         }
00254 
00255         MemoryStreamPtr ms(new MemoryStream());
00256         TextWriter writer(ms);
00257         XmlNodePtr node;
00258 
00259         if ( m_firstChild.Get() == m_lastChild.Get() && m_firstChild->IsText() )
00260         {
00261                 m_firstChild.ValidateMem();
00262                 m_firstChild->WriteTo( writer );
00263         }
00264         else
00265         {
00266                 for ( node = m_firstChild; node.IsNotNull(); node = node->NextSibling() )
00267                 {
00268                         m_firstChild.ValidateMem();
00269                         if ( node.Get() != m_firstChild.Get() )
00270                         {
00271                                 node->PreviousSibling()->ValidateMem();
00272                                 if ( /*NULL == node->ToText()  &&*/ ! node->PreviousSibling()->IsText() )
00273                                 {
00274                                         writer.Write( "\n" );
00275                                 }                               
00276                         }
00277                         node->WriteTo( writer );
00278                 }
00279         }
00280         return ms->ToString();  
00281 }
00282 
00283 StringPtr XmlElement::ToString() const
00284 {
00285         MemoryStreamPtr ms(new MemoryStream());
00286         TextWriter writer(ms);
00287         WriteTo(writer);
00288         return ms->ToString();  
00289 }
00290 
00291 XmlElementPtr XmlElement::ToElement() const 
00292 { 
00293         return (XmlNodePtr)m_self; 
00294 } 
00295 
00296 XmlElementPtr XmlElement::CreateElement(const String& name)
00297 {
00298         XmlElementPtr element(new XmlElement(name));
00299         XmlNodePtr xe = (XmlNodePtr)element;
00300         element->m_self = xe;
00301         return element;
00302 }
00303 
00304 #ifdef DEBUG
00305 void XmlElement::ValidateMem() const
00306 {
00307         XmlNode::ValidateMem();
00308         m_name.ValidateMem();
00309         m_attribs.ValidateMem();
00310 }
00311 
00312 void XmlElement::CheckMem() const
00313 {
00314         XmlNode::CheckMem();
00315         m_name.CheckMem();
00316         m_attribs.CheckMem();
00317 }
00318 #endif