Subversion Repositories HomeAutomation

Rev

Rev 1310 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*
  2.  * Node.cpp
  3.  *
  4.  *  Created on: Apr 26, 2009
  5.  *      Author: Mattias Runge
  6.  */
  7.  
  8. #include "Node.h"
  9.  
  10. namespace atom {
  11. namespace xml {
  12.  
  13. using namespace utils;
  14.  
  15. Node::Node()
  16. {
  17.     this->myIsEmpty = true;
  18.     LOG.setName("XML::Node");
  19. }
  20.  
  21. Node::Node(string filename)
  22. {
  23.     this->myIsEmpty = true;
  24.     LOG.setName("XML::Node");
  25.     this->parse(filename, file_get_contents(filename));
  26. }
  27.  
  28. Node::Node(string filename, string xmlData)
  29. {
  30.     this->myIsEmpty = true;
  31.     LOG.setName("XML::Node");
  32.     this->parse(filename, xmlData);
  33. }
  34.  
  35. void Node::parse(string filename, string xmlData)
  36. {
  37.     char c;
  38.     unsigned int position = 0;
  39.  
  40.     while (position < xmlData.length())
  41.     {
  42.         c = xmlData.at(position);
  43.  
  44.         switch (c)
  45.         {
  46.         case '<':
  47.             position = this->parseTag(filename, xmlData, position);
  48.             break;
  49.         }
  50.  
  51.         position++;
  52.     }
  53. }
  54.  
  55. string Node::tagName()
  56. {
  57.     return this->myTagName;
  58. }
  59.  
  60. Node::attributeList & Node::attributes()
  61. {
  62.     return this->myAttributes;
  63. }
  64.  
  65. string Node::operator [](string attributeName)
  66. {
  67.     attributeList::iterator iter = this->myAttributes.find(attributeName);
  68.  
  69.     if (iter == this->myAttributes.end())
  70.     {
  71.         return "";
  72.     }
  73.  
  74.     return iter->second;
  75. }
  76.  
  77. Node Node::selectFirst()
  78. {
  79.     // TODO Throw exception if returned list is empty
  80.     return this->select()[0];
  81. }
  82.  
  83. Node Node::selectFirst(string tagName)
  84. {
  85.     // TODO Throw exception if returned list is empty
  86.     return this->select(tagName)[0];
  87. }
  88.  
  89. Node Node::selectFirst(string tagName, attributeList attributes)
  90. {
  91.     // TODO Throw exception if returned list is empty
  92.     return this->select(tagName, attributes)[0];
  93. }
  94.  
  95. Node Node::selectFirst(string tagName, attributePair pair1)
  96. {
  97.     attributeList attributes;
  98.     attributes.insert(pair1);
  99.     return this->selectFirst(tagName, attributes);
  100. }
  101.  
  102. Node Node::selectFirst(string tagName, attributePair pair1, attributePair pair2)
  103. {
  104.     attributeList attributes;
  105.     attributes.insert(pair1);
  106.     attributes.insert(pair2);
  107.     return this->selectFirst(tagName, attributes);
  108. }
  109.  
  110. Node Node::selectFirst(string tagName, attributePair pair1, attributePair pair2, attributePair pair3)
  111. {
  112.     attributeList attributes;
  113.     attributes.insert(pair1);
  114.     attributes.insert(pair2);
  115.     attributes.insert(pair3);
  116.     return this->selectFirst(tagName, attributes);
  117. }
  118.  
  119. Node Node::selectFirst(string tagName, attributePair pair1, attributePair pair2, attributePair pair3, attributePair pair4)
  120. {
  121.     attributeList attributes;
  122.     attributes.insert(pair1);
  123.     attributes.insert(pair2);
  124.     attributes.insert(pair3);
  125.     attributes.insert(pair4);
  126.     return this->selectFirst(tagName, attributes);
  127. }
  128.  
  129. Node Node::selectFirst(string tagName, attributePair pair1, attributePair pair2, attributePair pair3, attributePair pair4, attributePair pair5)
  130. {
  131.     attributeList attributes;
  132.     attributes.insert(pair1);
  133.     attributes.insert(pair2);
  134.     attributes.insert(pair3);
  135.     attributes.insert(pair4);
  136.     attributes.insert(pair5);
  137.     return this->selectFirst(tagName, attributes);
  138. }
  139.  
  140. Node::nodeList Node::select()
  141. {
  142.     return this->myChildren;
  143. }
  144.  
  145. Node::nodeList Node::select(string tagName)
  146. {
  147.     attributeList attributes;
  148.     return this->select(tagName, attributes);
  149. }
  150.  
  151. Node::nodeList Node::select(string tagName, attributeList attributes)
  152. {
  153.     nodeList list;
  154.     bool attributesMatch = true;
  155.  
  156.     for (unsigned int n = 0; n < this->myChildren.size(); n++)
  157.     {
  158.         if (this->myChildren[n].tagName() == tagName)
  159.         {
  160.             attributesMatch = true;
  161.  
  162.             for (attributeList::iterator iter = attributes.begin(); iter != attributes.end(); iter++)
  163.             {
  164.                 //LOG.debug("#attributes = " + itos(this->myChildren[n].attributes().size()));
  165.                 //LOG.debug("iter->first = " + iter->first);
  166.                 //LOG.debug("iter->second = " + iter->second);
  167.                 //LOG.debug("this->myChildren[n][iter->first] = " + this->myChildren[n][iter->first]);
  168.                 if (this->myChildren[n][iter->first] != iter->second)
  169.                 {
  170.                     attributesMatch = false;
  171.                     break;
  172.                 }
  173.             }
  174.  
  175.             if (attributesMatch)
  176.             {
  177.                 list.push_back(myChildren[n]);
  178.             }
  179.         }
  180.     }
  181.  
  182.     return list;
  183. }
  184.  
  185.  
  186. Node::nodeList Node::select(string tagName, attributePair pair1)
  187. {
  188.     attributeList attributes;
  189.     attributes.insert(pair1);
  190.     return this->select(tagName, attributes);
  191. }
  192.  
  193. Node::nodeList Node::select(string tagName, attributePair pair1, attributePair pair2)
  194. {
  195.     attributeList attributes;
  196.     attributes.insert(pair1);
  197.     attributes.insert(pair2);
  198.     return this->select(tagName, attributes);
  199. }
  200.  
  201. Node::nodeList Node::select(string tagName, attributePair pair1, attributePair pair2, attributePair pair3)
  202. {
  203.     attributeList attributes;
  204.     attributes.insert(pair1);
  205.     attributes.insert(pair2);
  206.     attributes.insert(pair3);
  207.     return this->select(tagName, attributes);
  208. }
  209.  
  210. Node::nodeList Node::select(string tagName, attributePair pair1, attributePair pair2, attributePair pair3, attributePair pair4)
  211. {
  212.     attributeList attributes;
  213.     attributes.insert(pair1);
  214.     attributes.insert(pair2);
  215.     attributes.insert(pair3);
  216.     attributes.insert(pair4);
  217.     return this->select(tagName, attributes);
  218. }
  219.  
  220. Node::nodeList Node::select(string tagName, attributePair pair1, attributePair pair2, attributePair pair3, attributePair pair4, attributePair pair5)
  221. {
  222.     attributeList attributes;
  223.     attributes.insert(pair1);
  224.     attributes.insert(pair2);
  225.     attributes.insert(pair3);
  226.     attributes.insert(pair4);
  227.     attributes.insert(pair5);
  228.     return this->select(tagName, attributes);
  229. }
  230.  
  231. int Node::parseTag(string filename, string xmlData, unsigned int position)
  232. {
  233.     if (xmlData.at(position) != '<')
  234.     {
  235.         throw new Exception("Did not find < as expected. Character " + itos(position));
  236.     }
  237.  
  238.     position++;
  239.  
  240.     int endPosition = xmlData.find('>', position);
  241.  
  242.     if (xmlData.at(position) == '?' || xmlData.at(position) == '!' || xmlData.at(position) == '/')
  243.     {
  244.         return endPosition;
  245.     }
  246.  
  247.     this->myIsEmpty = false;
  248.  
  249.     string tagString;
  250.  
  251.     try
  252.     {
  253.         tagString = xmlData.substr(position, endPosition - position);
  254.     }
  255.     catch (std::out_of_range & e)
  256.     {
  257.         LOG.debug("parseTag exception: " + string(e.what()));
  258.         LOG.debug("A xmlData=" + xmlData + " :: position=" + itos(position) + " :: endPosition=" + itos(endPosition));
  259.         throw e;
  260.     }
  261.  
  262.     tagString = trim(tagString);
  263.     tagString = trim(tagString, '\n');
  264.     tagString = trim(tagString);
  265.     tagString += " ";
  266.  
  267.     bool foundEnd = false;
  268.     bool foundTag = false;
  269.     string buffer;
  270.     unsigned int pos = 0;
  271.     char c;
  272.     int s, e;
  273.  
  274.     while (pos < tagString.length())
  275.     {
  276.         c = tagString.at(pos);
  277.  
  278.         switch (c)
  279.         {
  280.         case ' ':
  281.             if (!foundTag)
  282.             {
  283.                 this->myTagName = buffer;
  284.                 buffer = "";
  285.                 //cout << "Found tag: " << myTagName << endl;
  286.                 foundTag = true;
  287.             }
  288.             break;
  289.  
  290.         case '/':
  291.             foundEnd = true;
  292.             break;
  293.  
  294.         case '=':
  295.             s = tagString.find('"', pos) + 1;
  296.             e = tagString.find('"', s);
  297.  
  298.             try
  299.             {
  300.                 this->myAttributes[buffer] = tagString.substr(s, e - s);
  301.                 //LOG.debug("Added attribute \"" + buffer + "\" = \"" + this->myAttributes[buffer] + "\"");
  302.             }
  303.             catch (std::out_of_range & ex)
  304.             {
  305.                 LOG.debug("parseTag exception: " + string(ex.what()));
  306.                 LOG.debug("A xmlData=" + xmlData + " :: position=" + itos(position) + " :: endPosition=" + itos(endPosition));
  307.                 throw ex;
  308.             }
  309.  
  310.             //cout << "Found attribute: " << buffer << " = " << myAttributes[buffer] << endl;
  311.             pos = e;
  312.             buffer = "";
  313.             break;
  314.  
  315.         default:
  316.             buffer += c;
  317.             break;
  318.         }
  319.  
  320.         pos++;
  321.     }
  322.  
  323.     position = endPosition;
  324.  
  325.     if (!foundEnd)
  326.     {
  327.         while (position < xmlData.length())
  328.         {
  329.             c = xmlData.at(position);
  330.  
  331.             switch (c)
  332.             {
  333.             case '<':
  334.                 if (xmlData.at(position + 1) == '/')
  335.                 {
  336.                     position += 2;
  337.                     endPosition = xmlData.find('>', position);
  338.  
  339.                     try
  340.                     {
  341.                         if (myTagName.compare(xmlData.substr(position, endPosition - position)) == 0)
  342.                         {
  343.                             //cout << "Found end tag: " << myTagName << endl;
  344.                             return endPosition;
  345.                         }
  346.                         else
  347.                         {
  348.                             throw new Exception("Invalid end tag found. " + xmlData.substr(position, endPosition - position) + "::" + myTagName);
  349.                         }
  350.                     }
  351.                     catch (std::out_of_range & ex)
  352.                     {
  353.                         LOG.debug("parseTag exception: " + string(ex.what()));
  354.                         LOG.debug("A xmlData=" + xmlData + " :: position=" + itos(position) + " :: endPosition=" + itos(endPosition));
  355.                         throw ex;
  356.                     }
  357.  
  358.                 }
  359.  
  360.                 Node subNode;
  361.                 position = subNode.parseTag(filename, xmlData, position);
  362.  
  363.                 if (!subNode.myIsEmpty)
  364.                 {
  365.                     this->myChildren.push_back(subNode);
  366.                 }
  367.  
  368.                 break;
  369.             }
  370.  
  371.             position++;
  372.         }
  373.     }
  374.  
  375.     return position;
  376. }
  377.  
  378. string Node::toString()
  379. {
  380.     string buffer = "<" + this->myTagName;
  381.  
  382.     for (attributeList::iterator iter = this->myAttributes.begin(); iter != this->myAttributes.end(); iter++)
  383.     {
  384.         buffer += " " + iter->first + "=\"" + iter->second + "\"";
  385.     }
  386.  
  387.     if (this->myChildren.size() > 0)
  388.     {
  389.         buffer += ">\n";
  390.  
  391.         for (unsigned int n = 0; n < this->myChildren.size(); n++)
  392.         {
  393.             buffer += this->myChildren[n].toString();
  394.         }
  395.  
  396.         buffer += "</" + this->myTagName + ">\n";
  397.     }
  398.     else
  399.     {
  400.         buffer += "/>\n";
  401.     }
  402.  
  403.     return buffer;
  404. }
  405.  
  406. }
  407. }
  408.