/*
WARNING: This header should never be directly included. Include XML.h instead.

Author:		Chris Kaynor (chris@kaynor.net)
Edited By:		

Description:		Provides an XML parser. See XML.h for additional details.
			
Usage:		Use either the constructor or one of the open functions to
			parse the specified XML. All elements and attributes are
			parsed into a tree accessable via the getElements()
			function or the getFirstElement() function.
			
Requirements:	string as defined in the standard template library.
			ifstream as defined in the standard template library.
			strstream as defined in the standard template library.
			XMLDocument as defined in kLibrary's XML section.
			Element as defined in kLibrary's XML section.
			Attribute as defined in kLibrary's XML section.
			Typedefs as defined in kLibrary's XML section (XML.h)
			
Last Edited:	June 24th, 2008
*/
/*
Copyright 2008 Chris Kaynor

This file is part of kLibrary.

kLibrary is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or(at your option) any later version.

kLibrary is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License.
*/

#ifndef KLIBRARY_XML_DOCUMENT_H
#define KLIBRARY_XML_DOCUMENT_H

#include "XML.h"

#include <string>

namespace kLibrary
{
	class XMLDocument
	{
	public:
		enum inputType
		{
			XML_XML,
			XML_File,
		};

		/*
		Instatiate the class. If a file or XML string is specified, load and parse it.
		*/
		XMLDocument(void);
		XMLDocument(const std::string& input, const inputType mode = XML_File);

		/*
		Load and parse the specified XML data. mode determines whether the string is
		a file or preloaded XML. This function calls one of the other open*() functions as
		mode specifies.
		*/
		void open(const std::string& input, const inputType mode = XML_File);
		
		/*
		Parse the XML contained in the string.
		if the XML cannot be parsed, the element tree will be empty.
		*/
		void openString(const std::string& XML);
		
		/*
		Load and parse the XML contained in the file specified by the string.
		If the file cannot be found, opened, or otherwise read, the elements
		tree will be empty.
		*/
		void openFile(const std::string& filename);

		/*
		Returns a constant refrence to _elements.
		*/
		const XML::elements& getElements(void) const;
		
		/*
		Returns an iterator to the first element parsed (generally the <?xml...?> element).
		*/
		const XML::elementIterator getFirstElement(void) const;
		
		/*
		Returns an iterator to the element just past the end of the tree.
		This may be used in conjunction with getFirstElement() to loop though the list as follows:
		
		for (XML::elementIterator cur = getFirstElement(); cur != getEndElement(); cur++)
		{
			...
			XML::Element myElement = *cur;
			...
		}
		*/
		const XML::elementIterator getEndElement(void) const;

		/*
		Finds the first occurrence of the element with the name elementName.
		Does not search recursively...the element must be contained directly
		within this element.
		The return is an iterator the same as if the client code looped though
		the elements, or the same as getEndElement() if the element was not found.
		*/
		const XML::elementIterator findFirstChildElement(const std::string& elementName) const;

	protected:

	private:
		/*
		Parses the input string, adding the element found into the output tree.
		Returns the number of characters parsed from the input string.
		*/
		const std::streamsize _parseString(const std::string& input, XML::elements& output);

		XML::elements _elements;
	};
}

#endif //KLIBRARY_XML_DOCUMENT_H