• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

MyGUI_XmlDocument.cpp

Go to the documentation of this file.
00001 
00007 /*
00008     This file is part of MyGUI.
00009 
00010     MyGUI is free software: you can redistribute it and/or modify
00011     it under the terms of the GNU Lesser General Public License as published by
00012     the Free Software Foundation, either version 3 of the License, or
00013     (at your option) any later version.
00014 
00015     MyGUI is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU Lesser General Public License for more details.
00019 
00020     You should have received a copy of the GNU Lesser General Public License
00021     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00022 */
00023 #include "MyGUI_Precompiled.h"
00024 #include "MyGUI_XmlDocument.h"
00025 #include "MyGUI_Common.h"
00026 #include "MyGUI_DataManager.h"
00027 
00028 namespace MyGUI
00029 {
00030     namespace xml
00031     {
00032 
00033         namespace utility
00034         {
00035             std::string convert_from_xml(const std::string& _string, bool& _ok)
00036             {
00037                 std::string ret;
00038                 _ok = true;
00039 
00040                 size_t pos = _string.find("&");
00041                 if (pos == std::string::npos) return _string;
00042 
00043                 ret.reserve(_string.size());
00044                 size_t old = 0;
00045                 while (pos != std::string::npos)
00046                 {
00047                     ret += _string.substr(old, pos - old);
00048 
00049                     size_t end = _string.find(";", pos + 1);
00050                     if (end == std::string::npos)
00051                     {
00052                         _ok = false;
00053                         return ret;
00054                     }
00055                     else
00056                     {
00057                         std::string tag = _string.substr(pos, end - pos + 1);
00058                         if (tag == "&amp;") ret += '&';
00059                         else if (tag == "&lt;") ret += '<';
00060                         else if (tag == "&gt;") ret += '>';
00061                         else if (tag == "&apos;") ret += '\'';
00062                         else if (tag == "&quot;") ret += '\"';
00063                         else
00064                         {
00065                             _ok = false;
00066                             return ret;
00067                         }
00068                     }
00069 
00070                     old = end + 1;
00071                     pos = _string.find("&", old);
00072                 };
00073                 ret += _string.substr(old, std::string::npos);
00074 
00075                 return ret;
00076             }
00077 
00078             std::string convert_to_xml(const std::string& _string)
00079             {
00080                 std::string ret;
00081 
00082                 size_t pos = _string.find_first_of("&<>'\"");
00083                 if (pos == std::string::npos) return _string;
00084 
00085                 ret.reserve(_string.size() * 2);
00086                 size_t old = 0;
00087                 while (pos != std::string::npos)
00088                 {
00089                     ret += _string.substr(old, pos - old);
00090 
00091                     if (_string[pos] == '&') ret += "&amp;";
00092                     else if (_string[pos] == '<') ret += "&lt;";
00093                     else if (_string[pos] == '>') ret += "&gt;";
00094                     else if (_string[pos] == '\'') ret += "&apos;";
00095                     else if (_string[pos] == '\"') ret += "&quot;";
00096 
00097                     old = pos + 1;
00098                     pos = _string.find_first_of("&<>'\"", old);
00099                 };
00100                 ret += _string.substr(old, std::string::npos);
00101 
00102                 return ret;
00103             }
00104 
00105         }
00106 
00107         //----------------------------------------------------------------------//
00108         // class ElementEnumerator
00109         //----------------------------------------------------------------------//
00110         ElementEnumerator::ElementEnumerator(VectorElement::iterator _begin, VectorElement::iterator _end) :
00111             m_first(true),
00112             m_current(_begin),
00113             m_end(_end)
00114         {
00115         }
00116 
00117         bool ElementEnumerator::next()
00118         {
00119             if (m_current == m_end) return false;
00120             else if (m_first)
00121             {
00122                 m_first = false;
00123                 return true;
00124             }
00125             ++ m_current;
00126             if (m_current == m_end) return false;
00127             return true;
00128         }
00129 
00130         bool ElementEnumerator::next(const std::string& _name)
00131         {
00132             while (next())
00133             {
00134                 if ((*m_current)->getName() == _name) return true;
00135             };
00136             return false;
00137         }
00138 
00139         //----------------------------------------------------------------------//
00140         // class Element
00141         //----------------------------------------------------------------------//
00142         Element::Element(const std::string &_name, ElementPtr _parent, ElementType _type, const std::string& _content) :
00143             mName(_name),
00144             mContent(_content),
00145             mParent(_parent),
00146             mType(_type)
00147         {
00148         }
00149 
00150         Element::~Element()
00151         {
00152             for (VectorElement::iterator iter=mChilds.begin(); iter!=mChilds.end(); ++iter)
00153             {
00154                 delete *iter;
00155             }
00156             mChilds.clear();
00157         }
00158 
00159         void Element::save(std::ostream& _stream, size_t _level)
00160         {
00161             // сначала табуляции намутим
00162             for (size_t tab=0; tab<_level; ++tab) _stream  << "    ";
00163 
00164             // теперь заголовок тега
00165             if (mType == ElementType::Declaration) _stream << "<?";
00166             else _stream << "<";
00167             _stream << mName;
00168 
00169             for (VectorAttributes::iterator iter = mAttributes.begin(); iter != mAttributes.end(); ++iter)
00170             {
00171                 _stream << " " << iter->first << "=\"" << utility::convert_to_xml(iter->second) << "\"";
00172             }
00173 
00174             bool empty = mChilds.empty();
00175             // если детей нет то закрываем
00176             if (empty && mContent.empty())
00177             {
00178                 if (mType == ElementType::Declaration) _stream << "?>\n";
00179                 else _stream << "/>\n";
00180             }
00181             else
00182             {
00183                 _stream << ">";
00184                 if (!empty) _stream << "\n";
00185                 // если есть тело то сначало оно
00186                 if (!mContent.empty())
00187                 {
00188                     if (!empty)
00189                     {
00190                         for (size_t tab=0; tab<=_level; ++tab) _stream  << "    ";
00191                     }
00192                     _stream << utility::convert_to_xml(mContent);
00193 
00194                     if (!empty) _stream << "\n";
00195                 }
00196                 // если есть детишки путь сохранятся
00197                 for (size_t child=0; child<mChilds.size(); child++)
00198                 {
00199                     mChilds[child]->save(_stream, _level + 1);
00200                 }
00201 
00202                 if (!empty)
00203                 {
00204                     for (size_t tab=0; tab<_level; ++tab)
00205                         _stream  << "    ";
00206                 }
00207                 _stream << "</" << mName << ">\n";
00208             }
00209 
00210         }
00211 
00212         ElementPtr Element::createChild(const std::string& _name, const std::string& _content)
00213         {
00214             ElementPtr node = new Element(_name, this, ElementType::Normal, _content);
00215             mChilds.push_back(node);
00216             return node;
00217         }
00218 
00219         void Element::clear()
00220         {
00221             for (VectorElement::iterator iter = mChilds.begin(); iter != mChilds.end(); ++iter) delete *iter;
00222             mChilds.clear();
00223             mContent.clear();
00224             mAttributes.clear();
00225         }
00226 
00227         bool Element::findAttribute(const std::string& _name, std::string& _value)
00228         {
00229             for (VectorAttributes::iterator iter=mAttributes.begin(); iter!=mAttributes.end(); ++iter)
00230             {
00231                 if ( (*iter).first == _name)
00232                 {
00233                     _value = (*iter).second;
00234                     return true;
00235                 }
00236             }
00237             return false;
00238         }
00239 
00240         std::string Element::findAttribute(const std::string& _name)
00241         {
00242             for (VectorAttributes::iterator iter=mAttributes.begin(); iter!=mAttributes.end(); ++iter)
00243             {
00244                 if ( (*iter).first == _name) return (*iter).second;
00245             }
00246             return "";
00247         }
00248 
00249         void Element::addAttribute(const std::string& _key, const std::string& _value)
00250         {
00251             mAttributes.push_back(PairAttribute(_key, _value));
00252         }
00253 
00254         void Element::removeAttribute(const std::string& _key)
00255         {
00256             for (size_t index=0; index<mAttributes.size(); ++index)
00257             {
00258                 if (mAttributes[index].first == _key)
00259                 {
00260                     mAttributes.erase(mAttributes.begin() + index);
00261                     return;
00262                 }
00263             }
00264         }
00265 
00266         ElementPtr Element::createCopy()
00267         {
00268             Element* elem = new Element(mName, nullptr, mType, mContent);
00269             elem->mAttributes = mAttributes;
00270 
00271             for (VectorElement::iterator iter=mChilds.begin(); iter!=mChilds.end(); ++iter)
00272             {
00273                 Element* child = (*iter)->createCopy();
00274                 child->mParent = elem;
00275                 elem->mChilds.push_back(child);
00276             }
00277 
00278             return elem;
00279         }
00280 
00281         void Element::setAttribute(const std::string& _key, const std::string& _value)
00282         {
00283             for (size_t index=0; index<mAttributes.size(); ++index)
00284             {
00285                 if (mAttributes[index].first == _key)
00286                 {
00287                     mAttributes[index].second = _value;
00288                     return;
00289                 }
00290             }
00291             mAttributes.push_back(PairAttribute(_key, _value));
00292         }
00293 
00294         void Element::addContent(const std::string& _content)
00295         {
00296             if (mContent.empty()) mContent = _content;
00297             else
00298             {
00299                 mContent += " ";
00300                 mContent += _content;
00301             }
00302         }
00303 
00304 #if MYGUI_COMPILER == MYGUI_COMPILER_MSVC && !defined(STLPORT)
00305         inline void open_stream(std::ofstream& _stream, const std::wstring& _wide) { _stream.open(_wide.c_str()); }
00306         inline void open_stream(std::ifstream& _stream, const std::wstring& _wide) { _stream.open(_wide.c_str()); }
00307 #else
00308         inline void open_stream(std::ofstream& _stream, const std::wstring& _wide) { _stream.open(UString(_wide).asUTF8_c_str()); }
00309         inline void open_stream(std::ifstream& _stream, const std::wstring& _wide) { _stream.open(UString(_wide).asUTF8_c_str()); }
00310 #endif
00311 
00312         //----------------------------------------------------------------------//
00313         // class Document
00314         //----------------------------------------------------------------------//
00315         Document::Document():
00316             mRoot(0),
00317             mDeclaration(0),
00318             mLastErrorFile(""),
00319             mLine(0),
00320             mCol(0)
00321         {
00322         }
00323 
00324         Document::~Document()
00325         {
00326             clear();
00327         }
00328 
00329         // открывает обычным файлом, имя файла в utf8
00330         bool Document::open(const std::string& _filename)
00331         {
00332             std::ifstream stream;
00333             stream.open(_filename.c_str());
00334 
00335             if (!stream.is_open())
00336             {
00337                 mLastError = ErrorType::OpenFileFail;
00338                 setLastFileError(_filename);
00339                 return false;
00340             }
00341 
00342             bool result = open(stream);
00343 
00344             stream.close();
00345             return result;
00346         }
00347 
00348         // открывает обычным файлом, имя файла в utf16 или utf32
00349         bool Document::open(const std::wstring& _filename)
00350         {
00351             std::ifstream stream;
00352             open_stream(stream, _filename);
00353 
00354             if (!stream.is_open())
00355             {
00356                 mLastError = ErrorType::OpenFileFail;
00357                 setLastFileError(_filename);
00358                 return false;
00359             }
00360 
00361             bool result = open(stream);
00362 
00363             stream.close();
00364             return result;
00365         }
00366 
00367         bool Document::open(std::istream& _stream)
00368         {
00369             DataStream* data = new DataStream(&_stream);
00370 
00371             bool result = open(data);
00372             delete data;
00373 
00374             return result;
00375         }
00376 
00377         // сохраняет файл, имя файла в кодировке utf8
00378         bool Document::save(const std::string& _filename)
00379         {
00380             std::ofstream stream;
00381             stream.open(_filename.c_str());
00382 
00383             if (!stream.is_open())
00384             {
00385                 mLastError = ErrorType::CreateFileFail;
00386                 setLastFileError(_filename);
00387                 return false;
00388             }
00389 
00390             bool result = save(stream);
00391 
00392             if (!result)
00393             {
00394                 setLastFileError(_filename);
00395             }
00396 
00397             stream.close();
00398             return result;
00399         }
00400 
00401         // сохраняет файл, имя файла в кодировке utf16 или utf32
00402         bool Document::save(const std::wstring& _filename)
00403         {
00404             std::ofstream stream;
00405             open_stream(stream, _filename);
00406 
00407             if (!stream.is_open())
00408             {
00409                 mLastError = ErrorType::CreateFileFail;
00410                 setLastFileError(_filename);
00411                 return false;
00412             }
00413 
00414             bool result = save(stream);
00415 
00416             if (!result)
00417             {
00418                 setLastFileError(_filename);
00419             }
00420 
00421             stream.close();
00422             return result;
00423         }
00424 
00425         // открывает обычным потоком
00426         bool Document::open(IDataStream* _stream)
00427         {
00428             clear();
00429 
00430             // это текущая строка для разбора
00431             std::string line;
00432             // это строка из файла
00433             std::string read;
00434             // текущий узел для разбора
00435             ElementPtr currentNode = 0;
00436 
00437             while (!_stream->eof())
00438             {
00439                 // берем новую строку
00440                 _stream->readline(read, '\n');
00441                 if (read.empty()) continue;
00442                 if (read[read.size()-1] == '\r') read.erase(read.size()-1, 1);
00443                 if (read.empty()) continue;
00444 
00445                 mLine ++;
00446                 mCol = 0; // потом проверить на многострочных тэгах
00447                 if (read.empty()) continue;
00448                 // текущая строка для разбора и то что еще прочитали
00449                 line += read;
00450 
00451                 if (!parseLine(line, currentNode))
00452                 {
00453                     return false;
00454                 }
00455 
00456             }; // while (!stream.eof())
00457 
00458             if (currentNode)
00459             {
00460                 mLastError = ErrorType::NotClosedElements;
00461                 return false;
00462             }
00463 
00464             return true;
00465         }
00466 
00467         bool Document::save(std::ostream& _stream)
00468         {
00469             if (!mDeclaration)
00470             {
00471                 mLastError = ErrorType::NoXMLDeclaration;
00472                 return false;
00473             }
00474 
00475             // заголовок utf8
00476             _stream << (char)0xEF;
00477             _stream << (char)0xBB;
00478             _stream << (char)0xBF;
00479 
00480             mDeclaration->save(_stream, 0);
00481             if (mRoot) mRoot->save(_stream, 0);
00482 
00483             return true;
00484         }
00485 
00486         void Document::clear()
00487         {
00488             clearDeclaration();
00489             clearRoot();
00490             mLine = 0;
00491             mCol = 0;
00492         }
00493 
00494         bool Document::parseTag(ElementPtr &_currentNode, std::string _content)
00495         {
00496 
00497             // убераем лишнее
00498             MyGUI::utility::trim(_content);
00499 
00500             if (_content.empty())
00501             {
00502                 // создаем пустой тег
00503                 if (_currentNode) _currentNode = _currentNode->createChild("");
00504                 else
00505                 {
00506                     _currentNode = new Element("", 0);
00507                     // если это первый то запоминаем
00508                     if (!mRoot) mRoot = _currentNode;
00509                 }
00510                 return true;
00511             }
00512 
00513             char simbol = _content[0];
00514             bool tag_info = false;
00515 
00516             if (simbol == '!') return true; // проверяем на коментарии
00517 
00518             // проверяем на информационный тег
00519             if (simbol == '?')
00520             {
00521                 tag_info = true;
00522                 _content.erase(0, 1); // удаляем первый символ
00523             }
00524 
00525             size_t start, end;
00526             // проверяем на закрытие тега
00527             if (simbol == '/')
00528             {
00529                 if (_currentNode == 0)
00530                 {
00531                     // чета мы закрывам а ниче даже и не открыто
00532                     if (!mRoot)
00533                     {
00534                         mLastError = ErrorType::CloseNotOpenedElement;
00535                         return false;
00536                     }
00537                 }
00538                 // обрезаем имя тэга
00539                 start = _content.find_first_not_of(" \t", 1);
00540                 if (start == _content.npos)
00541                 {
00542                     // тег пустой
00543                     _content.clear();
00544                 }
00545                 else
00546                 {
00547                     end = _content.find_last_not_of(" \t");
00548                     _content = _content.substr(start, end - start+1);
00549                 }
00550                 // проверяем соответствие открывающего и закрывающего тегов
00551                 if (_currentNode->getName() != _content)
00552                 {
00553                     mLastError = ErrorType::InconsistentOpenCloseElements;
00554                     return false;
00555                 }
00556                 // а теперь снижаем текущий узел вниз
00557                 _currentNode = _currentNode->getParent();
00558             }
00559             else
00560             {
00561                 // выделяем имя до первого пробела или закрывающего тега
00562                 std::string cut = _content;
00563                 start = _content.find_first_of(" \t/?", 1); // << превед
00564                 if (start != _content.npos)
00565                 {
00566                     cut = _content.substr(0, start);
00567                     _content = _content.substr(start);
00568                 }
00569                 else
00570                 {
00571                     _content.clear();
00572                 }
00573 
00574                 if (_currentNode) _currentNode = _currentNode->createChild(cut);
00575                 else
00576                 {
00577                     if (tag_info)
00578                     {
00579                         // информационный тег
00580                         if (mDeclaration)
00581                         {
00582                             mLastError = ErrorType::MoreThanOneXMLDeclaration;
00583                             return false;
00584                         }
00585                         _currentNode = new Element(cut, 0, ElementType::Comment);
00586                         mDeclaration = _currentNode;
00587                     }
00588                     else
00589                     {
00590                         // рутовый тег
00591                         if (mRoot)
00592                         {
00593                             mLastError = ErrorType::MoreThanOneRootElement;
00594                             return false;
00595                         }
00596                         _currentNode = new Element(cut, 0, ElementType::Normal);
00597                         mRoot = _currentNode;
00598                     }
00599                 }
00600 
00601                 // проверим на пустоту
00602                 start = _content.find_last_not_of(" \t");
00603                 if (start == _content.npos) return true;
00604 
00605                 // сразу отделим закрывающийся тэг
00606                 bool close = false;
00607                 if ((_content[start] == '/') || (_content[start] == '?'))
00608                 {
00609                     close = true;
00610                     // не будем резать строку, просто поставим пробел
00611                     _content[start] = ' ';
00612                     // проверим на пустоту
00613                     start = _content.find_last_not_of(" \t");
00614                     if (start == _content.npos)
00615                     {
00616                         // возвращаем все назад и уходим
00617                         _currentNode = _currentNode->getParent();
00618                         return true;
00619                     }
00620                 }
00621 
00622                 // а вот здесь уже в цикле разбиваем на атрибуты
00623                 while (true)
00624                 {
00625                     // ищем равно
00626                     start = _content.find('=');
00627                     if (start == _content.npos)
00628                     {
00629                         mLastError = ErrorType::IncorrectAttribute;
00630                         return false;
00631                     }
00632                     // ищем вторые ковычки
00633                     end = _content.find_first_of("\"\'", start+1);
00634                     if (end == _content.npos)
00635                     {
00636                         mLastError = ErrorType::IncorrectAttribute;
00637                         return false;
00638                     }
00639                     end = _content.find_first_of("\"\'", end+1);
00640                     if (end == _content.npos)
00641                     {
00642                         mLastError = ErrorType::IncorrectAttribute;
00643                         return false;
00644                     }
00645 
00646                     std::string key = _content.substr(0, start);
00647                     std::string value = _content.substr(start+1, end-start);
00648 
00649                     // проверка на валидность
00650                     if (! checkPair(key, value))
00651                     {
00652                         mLastError = ErrorType::IncorrectAttribute;
00653                         return false;
00654                     }
00655 
00656                     // добавляем пару в узел
00657                     _currentNode->addAttribute(key, value);
00658 
00659                     // следующий кусок
00660                     _content = _content.substr(end+1);
00661 
00662                     // в строке не осталось символов
00663                     start = _content.find_first_not_of(" \t");
00664                     if (start == _content.npos) break;
00665 
00666                     mCol += start;
00667                 };
00668 
00669                 // был закрывающий тег для текущего тега
00670                 if (close)
00671                 {
00672                     // не проверяем имена, потому что это наш тэг
00673                     _currentNode = _currentNode->getParent();
00674                 }
00675 
00676             }
00677             return true;
00678         }
00679 
00680         bool Document::checkPair(std::string &_key, std::string &_value)
00681         {
00682             // в ключе не должно быть ковычек и пробелов
00683             MyGUI::utility::trim(_key);
00684             if (_key.empty()) return false;
00685             size_t start = _key.find_first_of(" \t\"\'&");
00686             if (start != _key.npos) return false;
00687 
00688             // в значении, ковычки по бокам
00689             MyGUI::utility::trim(_value);
00690             if (_value.size() < 2) return false;
00691             if (((_value[0] != '"') || (_value[_value.length()-1] != '"')) &&
00692                 ((_value[0] != '\'') || (_value[_value.length()-1] != '\''))) return false;
00693             bool ok = true;
00694             _value = utility::convert_from_xml(_value.substr(1, _value.length() - 2), ok);
00695             return ok;
00696         }
00697 
00698         // ищет символ без учета ковычек
00699         size_t Document::find(const std::string& _text, char _char, size_t _start)
00700         {
00701             // ковычки
00702             bool kov = false;
00703 
00704             // буфер для поиска
00705             char buff[16] = "\"_\0";
00706             buff[1] = _char;
00707 
00708             size_t pos = _start;
00709 
00710             while (true)
00711             {
00712                 pos = _text.find_first_of(buff, pos);
00713 
00714                 // если уже конец, то досвидания
00715                 if (pos == _text.npos) break;
00716 
00717                 // нашли ковычку
00718                 else if (_text[pos] == '"')
00719                 {
00720                     kov = !kov;
00721                     pos ++;
00722                 }
00723                 // если мы в ковычках, то идем дальше
00724                 else if (kov) pos ++;
00725 
00726                 // мы не в ковычках
00727                 else break;
00728 
00729             };
00730 
00731             return pos;
00732         }
00733 
00734         void Document::clearDeclaration()
00735         {
00736             if (mDeclaration)
00737             {
00738                 delete mDeclaration;
00739                 mDeclaration = 0;
00740             }
00741         }
00742 
00743         void Document::clearRoot()
00744         {
00745             if (mRoot)
00746             {
00747                 delete mRoot;
00748                 mRoot = 0;
00749             }
00750         }
00751 
00752         ElementPtr Document::createDeclaration(const std::string& _version, const std::string& _encoding)
00753         {
00754             clearDeclaration();
00755             mDeclaration = new Element("xml", 0, ElementType::Declaration);
00756             mDeclaration->addAttribute("version", _version);
00757             mDeclaration->addAttribute("encoding", _encoding);
00758             return mDeclaration;
00759         }
00760 
00761         ElementPtr Document::createRoot(const std::string& _name)
00762         {
00763             clearRoot();
00764             mRoot = new Element(_name, 0, ElementType::Normal);
00765             return mRoot;
00766         }
00767 
00768         bool Document::parseLine(std::string& _line, ElementPtr& _element)
00769         {
00770             // крутимся пока в строке есть теги
00771             while (true)
00772             {
00773                 // сначала ищем по угловым скобкам
00774                 size_t start = find(_line, '<');
00775                 if (start == _line.npos) break;
00776                 size_t end = _line.npos;
00777 
00778                 // пытаемся вырезать многострочный коментарий
00779                 if ((start + 3 < _line.size()) && (_line[start + 1] == '!') && (_line[start + 2] == '-') && (_line[start + 3] == '-'))
00780                 {
00781                     end = _line.find("-->", start + 4);
00782                     if (end == _line.npos) break;
00783                     end += 2;
00784                 }
00785                 else
00786                 {
00787                     end = find(_line, '>', start+1);
00788                     if (end == _line.npos) break;
00789                 }
00790                 // проверяем на наличее тела
00791                 size_t body = _line.find_first_not_of(" \t<");
00792                 if (body < start)
00793                 {
00794                     std::string body_str = _line.substr(0, start);
00795                     // текущий символ
00796                     mCol = 0;
00797 
00798                     if (_element != 0)
00799                     {
00800                         bool ok = true;
00801                         _element->setContent(utility::convert_from_xml(body_str, ok));
00802                         if (!ok)
00803                         {
00804                             mLastError = ErrorType::IncorrectContent;
00805                             return false;
00806                         }
00807                     }
00808                 }
00809                 // вырезаем наш тэг и парсим
00810                 if (false == parseTag(_element, _line.substr(start+1, end-start-1)))
00811                 {
00812                     return false;
00813                 }
00814                 // и обрезаем текущую строку разбора
00815                 _line = _line.substr(end+1);
00816             };
00817             return true;
00818         }
00819 
00820         std::string Document::getLastError()
00821         {
00822             const std::string& error = mLastError.print();
00823             if (error.empty()) return error;
00824             return MyGUI::utility::toString("'", error, "' ,  file='", mLastErrorFile, "' ,  line=", mLine, " ,  col=", mCol);
00825         }
00826 
00827         /*Document Document::createCopyFromElement(ElementPtr _node)
00828         {
00829             Document doc;
00830             doc.mRoot = _node->createCopy();
00831             return doc;
00832         }*/
00833 
00834     } // namespace xml
00835 
00836 } // namespace MyGUI

Generated on Sun Jan 30 2011 for MyGUI by  doxygen 1.7.1