~scottydelicious666/brewtarget/brewtarget

« back to all changes in this revision

Viewing changes to src/xmlnode.cpp

  • Committer: Philip Greggory Lee
  • Date: 2009-08-23 16:53:43 UTC
  • Revision ID: git-v1:f8d1a25135bd92f06c46c562293800e4faa42c61
Made a src/ and ui/ directory and moved everything.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * xmlnode.cpp is part of Brewtarget, and is Copyright Philip G. Lee
 
3
 * (rocketman768@gmail.com), 2009.
 
4
 *
 
5
 * Brewtarget is free software: you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation, either version 3 of the License, or
 
8
 * (at your option) any later version.
 
9
 
 
10
 * Brewtarget is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include <string>
 
20
#include <vector>
 
21
#include <iostream>
 
22
#include <algorithm>
 
23
#include "stringparsing.h"
 
24
#include "xmlnode.h"
 
25
#include "xml.h"
 
26
 
 
27
void XmlNode::initMembers()
 
28
{
 
29
   tag = "";
 
30
   attributes = std::vector<std::string>();
 
31
   parent = NULL;
 
32
   children = std::vector<XmlNode*>();
 
33
   leafText = "";
 
34
}
 
35
 
 
36
XmlNode::XmlNode()
 
37
{
 
38
   initMembers();
 
39
}
 
40
 
 
41
void getAttributes( std::vector<std::string>& attrib, std::string::const_iterator &iter )
 
42
{
 
43
   std::string::const_iterator b;
 
44
   
 
45
   // Get the attributes.
 
46
   while(true)
 
47
   {
 
48
      // We are now one past the end of the tag.
 
49
      if( *iter == '>' )
 
50
         break;
 
51
      iterateUntilNotDelimiter( iter );
 
52
      b = iter;
 
53
      iterateUntilDelimiter(iter);
 
54
      attrib.push_back( replaceXmlCodes(removeQuotes(std::string(b,iter))) );
 
55
      
 
56
      // Want to push back the equals signs.
 
57
      if( *iter == '=' )
 
58
         attrib.push_back("=");
 
59
   }
 
60
}
 
61
 
 
62
std::string getNextTag( std::string::const_iterator &iter )
 
63
{
 
64
   std::string::const_iterator b;
 
65
   
 
66
   iterateUntilCharFound( iter, '<' );
 
67
   ++iter;
 
68
   b = iter;
 
69
   
 
70
   iterateUntilDelimiter( iter );
 
71
   
 
72
   return std::string(b, iter);
 
73
}
 
74
 
 
75
// iter should be on the end of the previous tag or
 
76
// the beginning of this tag.
 
77
XmlNode::XmlNode( std::string::const_iterator &iter, XmlNode* par )
 
78
{
 
79
   std::string::const_iterator b;
 
80
   XmlNode *tmpNode;
 
81
   
 
82
   initMembers();
 
83
 
 
84
   parent = par;
 
85
 
 
86
   while(true)
 
87
   {
 
88
      iterateUntilNotDelimiter(iter);
 
89
      if( *iter != '<' )
 
90
      {
 
91
         // Now we now that we are a leaf and only contain text.
 
92
         b = iter;
 
93
         iterateUntilCharFound( iter, '<' );
 
94
         leafText = replaceXmlCodes( std::string(b, iter) );
 
95
         return;
 
96
      }
 
97
      
 
98
      tag = getNextTag( iter ); // Not a leaf, so get tag.
 
99
      if( tag == "!--" ) // If this is an XML comment...
 
100
      {
 
101
         tag = "";
 
102
         // skip until the end of the comment...
 
103
         iterateUntilCharFound( iter, '>' );
 
104
         continue; // and try again.
 
105
      }
 
106
      else if( beginsWith(tag, "/") ) // Previous XmlNode should have parsed its own ending tag.
 
107
      {
 
108
         throw XmlNodeException("unexpected end tag: " + tag + "\nParent tag: " + parent->tag);
 
109
      }
 
110
      else
 
111
         break;
 
112
   } // end while(true)
 
113
   
 
114
   getAttributes( attributes, iter );
 
115
   
 
116
   // Get the children.
 
117
   while(true)
 
118
   {
 
119
      iterateUntilNotDelimiter(iter);
 
120
      b = iter;
 
121
      
 
122
      // Break if we reach the end tag.
 
123
      if( *iter == '<' && getNextTag( iter ) == ("/" + tag) )
 
124
         break;
 
125
      else
 
126
         iter = b; // Reset iter.
 
127
      
 
128
      tmpNode = new XmlNode(iter, this);
 
129
      children.push_back(tmpNode);
 
130
   }
 
131
}
 
132
 
 
133
bool XmlNode::isLeaf() const
 
134
{
 
135
   return children.size() == 0;
 
136
}
 
137
 
 
138
void XmlNode::printLeaves() const
 
139
{
 
140
   if( isLeaf() )
 
141
   {
 
142
      std::cout << "Leaf: \"" +leafText + "\" ";
 
143
      printParentTags();
 
144
      return;
 
145
   }
 
146
   
 
147
   unsigned int i, size = children.size();
 
148
   for( i = 0; i < size; ++i )
 
149
      children[i]->printLeaves();
 
150
}
 
151
 
 
152
void XmlNode::getNodesWithTag( std::vector<XmlNode*> &nodes, const std::string &inTag )
 
153
{
 
154
   if( tag == inTag )
 
155
      nodes.push_back(this);
 
156
   
 
157
   // Recursion base case.
 
158
   if( isLeaf() )
 
159
      return;
 
160
   
 
161
   unsigned int i, size = children.size();
 
162
   for( i = 0; i < size; ++i )
 
163
      children[i]->getNodesWithTag( nodes, inTag );
 
164
}
 
165
 
 
166
void XmlNode::getChildren( std::vector<XmlNode*>& v) const
 
167
{
 
168
   v.clear();
 
169
   copy( children.begin(), children.end(), back_inserter(v) );
 
170
   return;
 
171
}
 
172
 
 
173
const std::string& XmlNode::getTag() const
 
174
{
 
175
   return tag;
 
176
}
 
177
 
 
178
void XmlNode::printParentTags() const
 
179
{
 
180
   if( parent == NULL )
 
181
      return;
 
182
      
 
183
   std::cout << "<" + parent->tag + ">, ";
 
184
   parent->printParentTags();
 
185
}
 
186
 
 
187
void XmlNode::toXml( std::ostream& os, int indentLevel ) const
 
188
{
 
189
   unsigned int i;
 
190
   std::string indent( 3*indentLevel, ' ' );
 
191
   
 
192
   if( isLeaf() )
 
193
   {
 
194
      os << indent << leafText << std::endl;
 
195
      return;
 
196
   }
 
197
   
 
198
   // Output the beginning of the tag...
 
199
   os << indent << "<" + tag;
 
200
   // ...now all of the attributes...
 
201
   for( i = 0; i < attributes.size(); ++i )
 
202
   {
 
203
      if( attributes[i] == "=" )
 
204
         os << attributes[i];
 
205
      else
 
206
      {
 
207
         if( i > 0 && attributes[i-1] == "=" )
 
208
            os << attributes[i];
 
209
         else
 
210
            os << " " + attributes[i];
 
211
      }
 
212
   }
 
213
   // ...and finally the end of the tag.
 
214
   os << ">" << endl;
 
215
   
 
216
   // Now print all the children.
 
217
   for( i = 0; i < children.size(); ++i )
 
218
      children[i]->toXml( os, indentLevel+1 );
 
219
   
 
220
   // Now the closing tag.
 
221
   os << indent << "</" + tag + ">" << std::endl;
 
222
   
 
223
   return;
 
224
}
 
225
 
 
226
void XmlNode::addChild(XmlNode* child)
 
227
{
 
228
   if( child == 0 )
 
229
      return;
 
230
 
 
231
   children.push_back(child);
 
232
}
 
233
 
 
234
std::string XmlNode::getLeafText() const
 
235
{
 
236
   return leafText;
 
237
}