All pastes #174965 Raw Edit

Someone

public cpp v1 · immutable
·published 2006-09-18 11:27 UTC
rendered paste body
#include <iostream>#include <list>#include <fstream>#include <map>#include <cctype>#include <sstream>namespace xml{	class contents	{	public:		bool is_element;		std::string text;		contents()		{			is_element = false;		}		contents(std::string &text)		{			this->text = text;		}	};	class tag	{	public:		std::string name;		std::map<std::string, std::string> attributes;		void clear()		{			name.clear();			attributes.clear();		}	};	static wchar_t *entity_table[] = {	L"amp",		// &	L"lt",		// < 	L"gt"		// >	L"apos",	// '	L"quot"		// "	};	static wchar_t translated_table[] = {	L'&',	// amp	L'<',	// lt	L'>',	// gt	L'\'',	// '	L'"'	// "	};	class element : public tag, public contents	{	public:		std::list<contents*> sections;		element *parent;		element()		{			parent = 0;			is_element = true;		}		~element()		{			for(std::list<contents*>::iterator i=sections.begin(); i != sections.end(); ++i)			{				delete (*i);			}		}		element(tag &t)		{			element();			name = t.name;			attributes = t.attributes;		}		element(std::istream &s)		{			element();			load(s);		}		// Note: Could check if after the file is loaded that open_element == this.		// This would indicate that most likely everything went OK.		void load(std::istream &s)		{			parent = 0;			element *open_element = this;			text.clear();			attributes.clear();			sections.clear();			tag buf_tag; // Tag buffer.			std::string buf_gen; // Generic string buffer. Used for attribute values, and plain text contents.			std::string buf_ent; // Character entity buffer.			std::string buf_attr; // Attribute name buffer.			int open_tags = 0; // A counter for open tags to establish blocks.			unsigned int cur = 0; // Bit field with any of the following flags...			static const unsigned int cur_intag			= 0x1; // Currently processing a tag.			static const unsigned int cur_foundroot		= 0x2; // We found at least the root element.			static const unsigned int cur_ent			= 0x4; // Currently processing a character entity.			static const unsigned int cur_attr			= 0x8; // Currently processing an attribute.			static const unsigned int cur_str			= 0x10; // Currently processing an attribute value within quotes.			static const unsigned int cur_pastname		= 0x20; // The tag name was already found.			static const unsigned int cur_closing		= 0x40; // We found a forward slash in the tag.			static const unsigned int cur_opening		= 0x80; // The forward slash was not before the tag name.			static const unsigned int cur_declaration	= 0x100; // We are in the initial XML declaration I.E: <?xml version="1.0"?>.		//	while(open_tags || !(cur & cur_foundroot)) // Continue until we have found and closed the root element.			for(;;)			{				int c = s.get(); // Fetch next character from stream.				if(c == EOF)					break;				if(!(cur & cur_str)) // If we are not in a string.				{					// Conclusion: Tag syntactic stuff is OK.					if(c == '<') // Start tag					{//						open_element->text = buf_gen;						if(buf_gen.size()) // If we found some plain text.						{							// Add plain text contents to "sections" list.							open_element->sections.push_back(new contents(buf_gen));							buf_gen.clear();						}						cur |= cur_intag; // Set in-tag flag.						cur |= cur_opening; // Set tag-is-opening flag.						// This will be removed if a forward slash is found before the tag name.						continue; // Already identified the character.					}					if(c == '>') // End tag					{						if(cur & cur_closing) // If we found a slash before the tag name.						{							// Conclusion: This is a closing tag.							open_element->text = buf_gen;							open_element = open_element->parent; // Step back up to parent element.//							open_tags--; // One step closer to closing the root element.						}						else						{							// Conclusion: This is an opening tag for a new child element.							if(cur & cur_foundroot)							{								element *tmp = open_element; // Save open element								open_element = new element(buf_tag);								open_element->parent = tmp; // Set new child's parent								tmp->sections.push_back(open_element);							}							else							{								*this = buf_tag;								cur |= cur_foundroot; // Set found-root-element flag.							}//							open_element->text.clear();/*						if(tmp_text.size()) // If we have accumulated any text before this tag						{							// Add it as a contents							contents *tmp = open_element; // Save open element							contents *ns = new contents;							ns->text = tmp_text;							open_element->sections.push_back(ns);							tmp_text.clear();						}*///							open_tags++; // One step further from closing the root element.						}						// Clear flags used in tag, and tag name buffer.						cur &= ~cur_pastname;						cur &= ~cur_intag;						cur &= ~cur_closing;						buf_tag.clear();						continue; // Already identified the character.					}					if(c == '/') // If this character is a forward slash.					{						if(cur & cur_intag) // If we're in a tag.						{							cur |= cur_closing; // Set tag-is-closing flag.							if(buf_tag.name.empty())  // If we haven't gotten the tag name yet.							{								// Conclusion: This is ONLY a closing tag.								cur &= ~cur_opening; // Clear tag-is-opening flag.							}						}						continue;					}					if(c == '=') // If this character is an equal sign.					{						if(cur & cur_intag) // If inside a tag.						{							// Conclusion: This must be an attribute assignment operator.							cur |= cur_attr; // Set currently-assigning-attribute flag.						}						continue; // Already identified the character.					}				}				if(c == '"') // If this character is a quote mark.				{					if(cur & cur_intag) // If inside a tag.					{						if(cur & cur_attr) // If currently assigning an attribute.						{							if(cur & cur_str) // If already reading in a string.							{								// Conclusion: This is a closing quote mark for an attribute value.								buf_tag.attributes[buf_attr] = buf_gen;								buf_gen.clear();								buf_attr.clear();								cur &= ~cur_str; // Clear currently-reading-string flag.								cur &= ~cur_attr;  // Clear currently-assigning-attribute flag.							}							else							{								cur |= cur_str; // Set the currently-reading-string flag.							}						}					}					continue; // Already identified the character.				}				if(c == '&') // Start an entity				{					cur |= cur_ent;					continue; // Already identified the character.				}				if(c == ';') // End an entity				{					cur &= ~cur_ent;/*					for(int i=0; i < sizeof(entity_table); ++i)					{						//if( wcscmp(entity_table[i], buf_ent.c_str()) )						{						//	buf_gen += translated_table[i];						}					}*/					continue; // Already identified the character.				}				// What to expect inside a tag changes with whitespace.				if(std::isspace(c)) // If this character is whitespace.				{					if(cur & cur_intag) // If inside a tag					{						if(buf_tag.name.size()) // If tag name buffer is not empty.						{							// Conclusion: We are past the tag name and now reading attributes.							cur |= cur_pastname; // Set currently-past-name flag.						}					}					continue; // Already identified the character.				}				// No syntactic matches...				if(cur & cur_intag) // If inside a tag.				{					if(cur & cur_pastname) // If past the tag name					{						// Conclusion: Reading in attributes.						if(cur & cur_str) // If inside a string.						{							// Conclusion: Setting an attribute value.							if(cur & cur_ent) // If inside an entity							{								buf_ent += c; // Append this character to the entity buffer for conversion.							}							else							{								buf_gen += c; // Append this character directly to the attribute value buffer.							}						}						else						{							// Conclusion: Reading an attribute name, not a value.							buf_attr += c; // Append this character to the attribute name buffer.						}					}					else					{						// Conclusion: We are still reading in the tag name.						buf_tag.name += c; // Append character to temporary tag name buffer.					}				}				else // Not inside a tag				{					// Conclusion: Plain text contents.					buf_gen += c; // Append this character to the generic text buffer.				}			} // for(;;)		}	};	class file : element	{	public:		file(std::string filename)		{		}	};}void print_tabs(int indent){	while(indent)	{		std::cout << '\t';		indent--;	}}void print_elem(xml::element *elem, int indent=0){	for(std::list<xml::contents*>::iterator i=elem->sections.begin(); i != elem->sections.end(); ++i)	{		print_tabs(indent);		std::cout  << "section: " << (*i)->text << std::endl;		if((*i)->is_element)		{			xml::element *ass = (xml::element*)&*(*i);			print_elem(ass, indent+1);		}	}}int main(){	xml::element poop( std::ifstream("test.xml") );	print_elem(&poop);	system("pause");	return 0;}