Subversion Repositories HomeAutomation

Rev

Rev 969 | Go to most recent revision | Blame | Last modification | View Log | SVN | RSS feed

  1. /***************************************************************************
  2.  *   Copyright (C) November 30, 2008 by Mattias Runge                             *
  3.  *   mattias@runge.se                                                      *
  4.  *   xmlnode.cpp                                            *
  5.  *                                                                         *
  6.  *   This program is free software; you can redistribute it and/or modify  *
  7.  *   it under the terms of the GNU General Public License as published by  *
  8.  *   the Free Software Foundation; either version 2 of the License, or     *
  9.  *   (at your option) any later version.                                   *
  10.  *                                                                         *
  11.  *   This program is distributed in the hope that it will be useful,       *
  12.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  13.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  14.  *   GNU General Public License for more details.                          *
  15.  *                                                                         *
  16.  *   You should have received a copy of the GNU General Public License     *
  17.  *   along with this program; if not, write to the                         *
  18.  *   Free Software Foundation, Inc.,                                       *
  19.  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  20.  ***************************************************************************/
  21.  
  22. #include "xmlnode.h"
  23.  
  24. void XmlNode::load(string filename)
  25. {
  26.     parse(file_get_contents(filename));
  27. }
  28.  
  29. void XmlNode::parse(string xmlData)
  30. {
  31.     char c;
  32.     int position = 0;
  33.     while (position < xmlData.length())
  34.     {
  35.         c = xmlData.at(position);
  36.  
  37.         switch (c)
  38.         {
  39.             case '<':
  40.                 position = parseTag(xmlData, position);
  41.                 break;
  42.         }
  43.         position++;
  44.     }
  45. }
  46.  
  47. int XmlNode::parseTag(string xmlData, int position)
  48. {
  49.     if (xmlData.at(position) != '<')
  50.         throw new XmlException("Did not find < as expected. Character " + itos(position));
  51.  
  52.     position++;
  53.  
  54.     int endPosition = xmlData.find('>', position);
  55.  
  56.     if (xmlData.at(position) == '?' || xmlData.at(position) == '!' || xmlData.at(position) == '/')
  57.     {
  58.         return endPosition;
  59.     }
  60.  
  61.     string tagString;
  62.  
  63.     try
  64.     {
  65.         tagString = xmlData.substr(position, endPosition-position);
  66.     }
  67.     catch (std::out_of_range& e)
  68.     {
  69.         cout << "DEBUG: parseTag exception: " << e.what() << "\n";
  70.         cout << "DEBUG: A xmlData=" << xmlData << " :: position=" << position << " :: endPosition=" << endPosition << endl;
  71.     }
  72.  
  73.     tagString = trim(tagString);
  74.     tagString = trim(tagString, '\n');
  75.     tagString = trim(tagString);
  76.     tagString += " ";
  77.  
  78.     bool foundEnd = false;
  79.     bool foundTag = false;
  80.     string buffer;
  81.     int pos = 0;
  82.     char c;
  83.     int s, e;
  84.  
  85.     while (pos < tagString.length())
  86.     {
  87.         c = tagString.at(pos);
  88.  
  89.         switch (c)
  90.         {
  91.             case ' ':
  92.                 if (!foundTag)
  93.                 {
  94.                     myTagName = buffer;
  95.                     buffer = "";
  96.                     //cout << "Found tag: " << myTagName << endl;
  97.                     foundTag = true;
  98.                 }
  99.                 break;
  100.  
  101.             case '/':
  102.                 foundEnd = true;
  103.                 break;
  104.  
  105.             case '=':
  106.                 s = tagString.find('"', pos)+1;
  107.                 e = tagString.find('"', s);
  108.  
  109.                 try
  110.                 {
  111.                     myAttributes[buffer] = tagString.substr(s, e-s);
  112.                 }
  113.                 catch (std::out_of_range& ex)
  114.                 {
  115.                     cout << "DEBUG: parseTag exception: " << ex.what() << "\n";
  116.                     cout << "DEBUG: B tagString=" << tagString << " :: s=" << s << " :: e=" << e << endl;
  117.                     continue;
  118.                 }
  119.  
  120.  
  121.                 //cout << "Found attribute: " << buffer << " = " << myAttributes[buffer] << endl;
  122.                 pos = e;
  123.                 buffer = "";
  124.                 break;
  125.  
  126.             default:
  127.                 buffer += c;
  128.                 break;
  129.         }
  130.         pos++;
  131.     }
  132.    
  133.     position = endPosition;
  134.  
  135.     if (!foundEnd)
  136.     {
  137.         while (position < xmlData.length())
  138.         {
  139.             c = xmlData.at(position);
  140.  
  141.             switch (c)
  142.             {
  143.                 case '<':
  144.                     if (xmlData.at(position+1) == '/')
  145.                     {
  146.                         position += 2;
  147.                         endPosition = xmlData.find('>', position);
  148.  
  149.                         try
  150.                         {
  151.                             if (myTagName.compare(xmlData.substr(position, endPosition-position)) == 0)
  152.                             {
  153.                                 //cout << "Found end tag: " << myTagName << endl;
  154.                                 return endPosition;
  155.                             }
  156.                             else
  157.                             {
  158.                                 throw new XmlException("Invalid end tag found. " + xmlData.substr(position, endPosition-position) + "::" + myTagName);
  159.                             }
  160.                         }
  161.                         catch (std::out_of_range& e)
  162.                         {
  163.                             cout << "DEBUG: parseTag exception: " << e.what() << "\n";
  164.                             cout << "DEBUG: C xmlData=" << xmlData << " :: position=" << position << " :: endPosition=" << endPosition << endl;
  165.                             continue;
  166.                         }
  167.  
  168.                        
  169.                     }
  170.  
  171.                     XmlNode subNode;
  172.                     position = subNode.parseTag(xmlData, position);
  173.                     myChildren.push_back(subNode);
  174.                     break;
  175.             }
  176.  
  177.             position++;
  178.         }
  179.     }
  180.  
  181.     return position;
  182. }
  183.  
  184. XmlNode XmlNode::findChild(string tagName)
  185. {
  186.     for (int n = 0; n < myChildren.size(); n++)
  187.     {
  188.         if (myChildren[n].getTagName().compare(tagName) == 0)
  189.             return myChildren[n];
  190.     }
  191.  
  192.     XmlNode defaultNode;
  193.  
  194.     return defaultNode;
  195. }
  196.  
  197. string XmlNode::getAttributeValue(string attributeName)
  198. {
  199.     map<string, string>::const_iterator iterator = myAttributes.find(attributeName);
  200.  
  201.     if (iterator == myAttributes.end())
  202.         return NULL;
  203.  
  204.     return iterator->second;
  205. }
  206.