#include "Element.h"
#include "TextNode.h"
#include "Comment.h"
namespace xml
{
Element::Element(const std::string& name)
: Node(nodeElement)
{
this->nodeName = name.substr(1);
}
Element::~Element()
{
}
std::istream& Element::load(std::istream& in)
{
// if this is an empty tag with no attributes
if ( nodeName[nodeName.length() - 1] == '/' )
{
nodeName = nodeName.substr(0, nodeName.length() - 1);
return in;
}
// Read children: attributes, child elements, text nodes, comments
for ( std::string token = Util::nextToken(in); in; token = Util::nextToken(in) )
{
size_t pos = std::string::npos;
if ( (pos = token.find('=')) != std::string::npos )
{
// Found an attribute
std::string name = token.substr(0, pos);
attributes[name] = token.substr(pos + 1);
if ( token[token.length() - 1] == '/' )
return in;
}
else if ( token[0] == '<' )
{
if ( token[1] == '/' )
{
// Found end-tag for this element
return in;
}
else if ( token[1] == '!' )
{
// Found a comment
Comment* comment = new Comment();
childNodes.push_back(comment);
comment->load(in);
}
else
{
// Found a child element
Element* child = new Element(token);
childNodes.push_back(child);
child->load(in);
}
}
else
{
// Found a text node, include the removed separator
in.unget();
TextNode* text = new TextNode(token + (char)in.get());
childNodes.push_back(text);
text->load(in);
}
}
return in;
}
std::ostream&Element::print(std::ostream& out, int depth) const
{
// Indent
Util::tabs(out, depth);
// Print open tag and attributes: first << '=' << itr->second;
// If empty element, print empty tag
if ( childNodes.size() == 0 )
return out << "/>" << std::endl;
// Has children, close start tag and print each child in one line
out << '>' << std::endl;
for ( size_t i = 0; i < childNodes.size(); ++i )
childNodes[i]->print(out, depth + 1);
return Util::tabs(out, depth) << "" << nodeName << '>' << std::endl; // end-tag
}
} // namespace xml