Subversion Repositories HomeAutomation

Rev

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