Subversion Repositories HomeAutomation

Rev

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