2
* xmlnode.cpp is part of Brewtarget, and is Copyright Philip G. Lee
3
* (rocketman768@gmail.com), 2009.
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.
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.
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/>.
23
#include "stringparsing.h"
27
void XmlNode::initMembers()
30
attributes = std::vector<std::string>();
32
children = std::vector<XmlNode*>();
41
void getAttributes( std::vector<std::string>& attrib, std::string::const_iterator &iter )
43
std::string::const_iterator b;
45
// Get the attributes.
48
// We are now one past the end of the tag.
51
iterateUntilNotDelimiter( iter );
53
iterateUntilDelimiter(iter);
54
attrib.push_back( replaceXmlCodes(removeQuotes(std::string(b,iter))) );
56
// Want to push back the equals signs.
58
attrib.push_back("=");
62
std::string getNextTag( std::string::const_iterator &iter )
64
std::string::const_iterator b;
66
iterateUntilCharFound( iter, '<' );
70
iterateUntilDelimiter( iter );
72
return std::string(b, iter);
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 )
79
std::string::const_iterator b;
88
iterateUntilNotDelimiter(iter);
91
// Now we now that we are a leaf and only contain text.
93
iterateUntilCharFound( iter, '<' );
94
leafText = replaceXmlCodes( std::string(b, iter) );
98
tag = getNextTag( iter ); // Not a leaf, so get tag.
99
if( tag == "!--" ) // If this is an XML comment...
102
// skip until the end of the comment...
103
iterateUntilCharFound( iter, '>' );
104
continue; // and try again.
106
else if( beginsWith(tag, "/") ) // Previous XmlNode should have parsed its own ending tag.
108
throw XmlNodeException("unexpected end tag: " + tag + "\nParent tag: " + parent->tag);
114
getAttributes( attributes, iter );
119
iterateUntilNotDelimiter(iter);
122
// Break if we reach the end tag.
123
if( *iter == '<' && getNextTag( iter ) == ("/" + tag) )
126
iter = b; // Reset iter.
128
tmpNode = new XmlNode(iter, this);
129
children.push_back(tmpNode);
133
bool XmlNode::isLeaf() const
135
return children.size() == 0;
138
void XmlNode::printLeaves() const
142
std::cout << "Leaf: \"" +leafText + "\" ";
147
unsigned int i, size = children.size();
148
for( i = 0; i < size; ++i )
149
children[i]->printLeaves();
152
void XmlNode::getNodesWithTag( std::vector<XmlNode*> &nodes, const std::string &inTag )
155
nodes.push_back(this);
157
// Recursion base case.
161
unsigned int i, size = children.size();
162
for( i = 0; i < size; ++i )
163
children[i]->getNodesWithTag( nodes, inTag );
166
void XmlNode::getChildren( std::vector<XmlNode*>& v) const
169
copy( children.begin(), children.end(), back_inserter(v) );
173
const std::string& XmlNode::getTag() const
178
void XmlNode::printParentTags() const
183
std::cout << "<" + parent->tag + ">, ";
184
parent->printParentTags();
187
void XmlNode::toXml( std::ostream& os, int indentLevel ) const
190
std::string indent( 3*indentLevel, ' ' );
194
os << indent << leafText << std::endl;
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 )
203
if( attributes[i] == "=" )
207
if( i > 0 && attributes[i-1] == "=" )
210
os << " " + attributes[i];
213
// ...and finally the end of the tag.
216
// Now print all the children.
217
for( i = 0; i < children.size(); ++i )
218
children[i]->toXml( os, indentLevel+1 );
220
// Now the closing tag.
221
os << indent << "</" + tag + ">" << std::endl;
226
void XmlNode::addChild(XmlNode* child)
231
children.push_back(child);
234
std::string XmlNode::getLeafText() const