/// <summary>
        /// Gets the next event from the XML stream
        /// </summary>
        /// <returns></returns>
        public IRdfXmlEvent GetNextEvent()
        {
            if (_stop)
            {
                return(null);
            }

            // If the Root Element is filled then return it
            if (_rootEl != null)
            {
                IRdfXmlEvent temp = _rootEl;
                _rootEl = null;
                return(temp);
            }

            // If Literal Parsing flag is set then we've just read an element which had rdf:parseType="Literal"
            if (_parseLiteral)
            {
                _requireEndElement = true;
                _parseLiteral      = false;
                _noRead            = true;
                _reader.MoveToContent();
                String data = _reader.ReadInnerXml();
                return(new TypedLiteralEvent(data, RdfSpecsHelper.RdfXmlLiteral, data, GetPosition()));
            }

            // If we need to return an end element then do so
            if (_requireEndElement)
            {
                _requireEndElement = false;
                _currentBaseUri    = _baseUris.Pop();
                return(new EndElementEvent(GetPosition()));
            }

            // If at EOF throw an error
            if (_reader.EOF)
            {
                throw new RdfParseException("Unable to read further events as the end of the stream has already been reached");
            }

            // Otherwise attempt to read the next node
            bool read = true;

            if (!_noRead)
            {
                read = _reader.Read();
            }
            else
            {
                _noRead = false;
            }
            if (read)
            {
                // Return the appropriate event for the Node Type
                switch (_reader.NodeType)
                {
                case XmlNodeType.Element:
                    // Element
                    if (_first)
                    {
                        _first       = false;
                        _rdfRootSeen = IsName("RDF", NamespaceMapper.RDF);
                        _rootEl      = GetElement();
                        RootEvent root = new RootEvent(GetBaseUri(), _reader.Value, GetPosition());
                        root.DocumentElement = (ElementEvent)_rootEl;
                        root.Children.Add((ElementEvent)_rootEl);

                        if (root.BaseUri.Equals(String.Empty))
                        {
                            root.BaseUri = _currentBaseUri;
                        }

                        return(root);
                    }
                    else
                    {
                        if (!_first && IsName("RDF", NamespaceMapper.RDF))
                        {
                            if (_rdfRootSeen)
                            {
                                throw new RdfParseException("Unexpected nested rdf:RDF node encountered, this is not valid RDF/XML syntax");
                            }
                            _noRead = true;
                            _first  = true;
                            return(new ClearQueueEvent());
                        }
                        return(GetElement());
                    }

                case XmlNodeType.EndElement:
                    // End of an Element
                    _currentBaseUri = _baseUris.Pop();
                    if (IsName("RDF", NamespaceMapper.RDF))
                    {
                        _stop = true;
                    }
                    return(new EndElementEvent(GetPosition()));

                case XmlNodeType.Attribute:
                    // Attribute
                    throw new RdfParseException("Unexpected Attribute Node encountered");

                case XmlNodeType.Text:
                    return(new TextEvent(_reader.Value, _reader.Value, GetPosition()));

                case XmlNodeType.CDATA:
                    return(new TextEvent(_reader.Value, _reader.Value, GetPosition()));

                case XmlNodeType.Document:
                case XmlNodeType.DocumentType:
                case XmlNodeType.XmlDeclaration:
                case XmlNodeType.Comment:
                case XmlNodeType.ProcessingInstruction:
                case XmlNodeType.Notation:
                case XmlNodeType.Whitespace:
                    // Node Types that don't generate events and just indicate to continue reading
                    return(GetNextEvent());

                default:
                    throw new RdfParseException("Unexpected XML Node Type " + _reader.NodeType.ToString() + " encountered");
                }
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Gets the next event from the XML stream
        /// </summary>
        /// <returns></returns>
        public IRdfXmlEvent GetNextEvent()
        {
            if (this._stop) return null;

            //If the Root Element is filled then return it
            if (this._rootEl != null)
            {
                IRdfXmlEvent temp = this._rootEl;
                this._rootEl = null;
                return temp;
            }

            //If Literal Parsing flag is set then we've just read an element which had rdf:parseType="Literal"
            if (this._parseLiteral)
            {
                this._requireEndElement = true;
                this._parseLiteral = false;
                this._noRead = true;
                this._reader.MoveToContent();
                String data = this._reader.ReadInnerXml();
                return new TypedLiteralEvent(data, RdfSpecsHelper.RdfXmlLiteral, data, this.GetPosition());
            }

            //If we need to return an end element then do so
            if (this._requireEndElement)
            {
                this._requireEndElement = false;
                this._currentBaseUri = this._baseUris.Pop();
                return new EndElementEvent(this.GetPosition());
            }

            //If at EOF throw an error
            if (this._reader.EOF) throw new RdfParseException("Unable to read further events as the end of the stream has already been reached");

            //Otherwise attempt to read the next node
            bool read = true;
            if (!this._noRead)
            {
                read = this._reader.Read();
            }
            else
            {
                this._noRead = false;
            }
            if (read)
            {
                //Return the appropriate event for the Node Type
                switch (this._reader.NodeType)
                {
                    case XmlNodeType.Element:
                        //Element
                        if (this._first)
                        {
                            this._first = false;
                            this._rdfRootSeen = this.IsName("RDF", NamespaceMapper.RDF);
                            this._rootEl = this.GetElement();
                            RootEvent root = new RootEvent(this.GetBaseUri(), this._reader.Value, this.GetPosition());
                            root.DocumentElement = (ElementEvent)this._rootEl;
                            root.Children.Add((ElementEvent)this._rootEl);
                            return root;
                        }
                        else
                        {
                            if (!this._first && this.IsName("RDF", NamespaceMapper.RDF))
                            {
                                if (this._rdfRootSeen) throw new RdfParseException("Unexpected nested rdf:RDF node encountered, this is not valid RDF/XML syntax");
                                this._noRead = true;
                                this._first = true;
                                return new ClearQueueEvent();
                            }
                            return this.GetElement();
                        }

                    case XmlNodeType.EndElement:
                        //End of an Element
                        this._currentBaseUri = this._baseUris.Pop();
                        if (this.IsName("RDF", NamespaceMapper.RDF))
                        {
                            this._stop = true;
                        }
                        return new EndElementEvent(this.GetPosition());

                    case XmlNodeType.Attribute:
                        //Attribute
                        throw new RdfParseException("Unexpected Attribute Node encountered");

                    case XmlNodeType.Text:
                        return new TextEvent(this._reader.Value, this._reader.Value, this.GetPosition());

                    case XmlNodeType.CDATA:
                        return new TextEvent(this._reader.Value, this._reader.Value, this.GetPosition());

                    case XmlNodeType.Document:
                    case XmlNodeType.DocumentType:
                    case XmlNodeType.XmlDeclaration:
                    case XmlNodeType.Comment:
                    case XmlNodeType.ProcessingInstruction:
                    case XmlNodeType.Notation:
                    case XmlNodeType.Whitespace:
                        //Node Types that don't generate events and just indicate to continue reading
                        return this.GetNextEvent();

                    default:
                        throw new RdfParseException("Unexpected XML Node Type " + this._reader.NodeType.ToString() + " encountered");
                }
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// Given an XML Node that is the Root of the RDF/XML section of the Document Tree creates the RootEvent and generates the rest of the Event Tree by recursive calls to the <see cref="GenerateEvents">GenerateEvents</see> method
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="docEl">XML Node that is the Root of the RDF/XML section of the Document Tree</param>
        /// <returns></returns>
        private RootEvent GenerateEventTree(RdfXmlParserContext context, XmlNode docEl)
        {
            // Get the Document Element
            // XmlNode docEl = document.DocumentElement;

            // Generate a Root Event and Element Event from it
            RootEvent root = new RootEvent(docEl.BaseURI, docEl.OuterXml);

            if (docEl.BaseURI.Equals(String.Empty))
            {
                if (context.BaseUri != null)
                {
                    root.BaseUri = context.BaseUri.AbsoluteUri;
                }
            }
            ElementEvent element = new ElementEvent(docEl.LocalName, docEl.Prefix, root.BaseUri, docEl.OuterXml);

            // Initialise Language Settings
            root.Language    = String.Empty;
            element.Language = root.Language;

            // Set as Document Element and add as only Child
            root.DocumentElement = element;
            root.Children.Add(element);

            #region Attribute Processing

            // Go through attributes looking for XML Namespace Declarations
            foreach (XmlAttribute attr in docEl.Attributes)
            {
                if (attr.Prefix.Equals("xmlns") || attr.Name == "xmlns")
                {
                    // Define a Namespace
                    String prefix = attr.LocalName;
                    if (prefix.Equals("xmlns"))
                    {
                        prefix = String.Empty;
                    }
                    String uri;
                    if (attr.Value.StartsWith("http://"))
                    {
                        // Absolute Uri
                        uri = attr.Value;
                    }
                    else if (!root.BaseUri.Equals(String.Empty))
                    {
                        // Relative Uri with a Base Uri to resolve against
                        // uri = root.BaseUri + attr.Value;
                        uri = Tools.ResolveUri(attr.Value, root.BaseUri);
                    }
                    else
                    {
                        // Relative Uri with no Base Uri
                        throw new RdfParseException("Cannot resolve a Relative Namespace URI since there is no in-scope Base URI");
                    }
                    context.Namespaces.AddNamespace(prefix, UriFactory.Create(uri));
                }
                else if (attr.Name == "xml:base")
                {
                    // Set the Base Uri
                    String baseUri = attr.Value;

                    if (RdfXmlSpecsHelper.IsAbsoluteURI(baseUri))
                    {
                        // Absolute Uri
                        root.BaseUri = baseUri;
                    }
                    else if (!element.BaseUri.Equals(String.Empty))
                    {
                        // Relative Uri with a Base Uri to resolve against
                        // root.BaseUri += baseUri;
                        root.BaseUri = Tools.ResolveUri(baseUri, root.BaseUri);
                    }
                    else
                    {
                        // Relative Uri with no Base Uri
                        throw new RdfParseException("Cannot resolve a Relative Base URI since there is no in-scope Base URI");
                    }
                    element.BaseUri = root.BaseUri;
                }
            }

            #endregion

            // Iterate over Children
            foreach (XmlNode child in docEl.ChildNodes)
            {
                // Ignore Irrelevant Node Types
                if (IsIgnorableNode(child))
                {
                    continue;
                }

                // Generate an Event for the Child Node
                ElementEvent childEvent = GenerateEvents(context, child, element);
                element.Children.Add(childEvent);
            }

            // Return the Root Event
            return(root);
        }
        /// <summary>
        /// Takes the Event Tree and Flattens it into a Queue as per the rules laid out in the RDF/XML Specification
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="evt">Event which is the Root of the Tree (not necessarily a RootEvent)</param>
        /// <param name="nesting">A numeric value used for Parser Tracing to indicate nesting levels of the Event Tree</param>
        private void FlattenEventTree(RdfXmlParserContext context, IRdfXmlEvent evt, int nesting)
        {
            // Add to Queue
            context.Events.Enqueue(evt);

            if (context.TraceParsing)
            {
                Console.Write(nesting + " " + evt.GetType().ToString());
            }

            // Iterate over Children where present
            if (evt is RootEvent)
            {
                RootEvent root = (RootEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine("");
                }
                foreach (IRdfXmlEvent childEvent in root.Children)
                {
                    FlattenEventTree(context, childEvent, nesting + 1);
                }

                // No End after a RootEvent
                return;
            }
            else if (evt is ElementEvent)
            {
                ElementEvent element = (ElementEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine(" " + element.Namespace + ":" + element.LocalName);
                }
                if (element.Children.Count > 0)
                {
                    foreach (IRdfXmlEvent childEvent in element.Children)
                    {
                        FlattenEventTree(context, childEvent, nesting + 1);
                    }
                }
            }
            else if (evt is TextEvent)
            {
                TextEvent text = (TextEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine(" " + text.Value);
                }

                // No additional End after a Text Event
                return;
            }
            else if (evt is TypedLiteralEvent)
            {
                TypedLiteralEvent tlit = (TypedLiteralEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine();
                }

                // No additional End after a Text Event
                return;
            }

            // Add an End Element Event to the Queue
            EndElementEvent end = new EndElementEvent();

            context.Events.Enqueue(end);
            if (context.TraceParsing)
            {
                String endDescrip = String.Empty;
                if (evt is ElementEvent)
                {
                    ElementEvent temp = (ElementEvent)evt;
                    endDescrip = " " + temp.QName;
                }
                Console.WriteLine(nesting + " " + end.GetType().ToString() + endDescrip);
            }
        }
        /// <summary>
        /// Given an XML Node that is the Root of the RDF/XML section of the Document Tree creates the RootEvent and generates the rest of the Event Tree by recursive calls to the <see cref="GenerateEvents">GenerateEvents</see> method
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="docEl">XML Node that is the Root of the RDF/XML section of the Document Tree</param>
        /// <returns></returns>
        private RootEvent GenerateEventTree(RdfXmlParserContext context, XmlNode docEl)
        {
            //Get the Document Element
            //XmlNode docEl = document.DocumentElement;

            //Generate a Root Event and Element Event from it
            RootEvent root = new RootEvent(docEl.BaseURI, docEl.OuterXml);
            if (docEl.BaseURI.Equals(String.Empty))
            {
                if (context.BaseUri != null)
                {
                    root.BaseUri = context.BaseUri.ToString();
                }
            }
            ElementEvent element = new ElementEvent(docEl.LocalName, docEl.Prefix, root.BaseUri, docEl.OuterXml);

            //Initialise Language Settings
            root.Language = String.Empty;
            element.Language = root.Language;

            //Set as Document Element and add as only Child
            root.DocumentElement = element;
            root.Children.Add(element);

            #region Attribute Processing

            //Go through attributes looking for XML Namespace Declarations
            foreach (XmlAttribute attr in docEl.Attributes)
            {
                if (attr.Prefix.Equals("xmlns") || attr.Name == "xmlns")
                {
                    //Define a Namespace
                    String prefix = attr.LocalName;
                    if (prefix.Equals("xmlns")) prefix = String.Empty;
                    String uri;
                    if (attr.Value.StartsWith("http://"))
                    {
                        //Absolute Uri
                        uri = attr.Value;
                    }
                    else if (!root.BaseUri.Equals(String.Empty))
                    {
                        //Relative Uri with a Base Uri to resolve against
                        //uri = root.BaseUri + attr.Value;
                        uri = Tools.ResolveUri(attr.Value, root.BaseUri);
                    }
                    else
                    {
                        //Relative Uri with no Base Uri
                        throw new RdfParseException("Cannot resolve a Relative Namespace URI since there is no in-scope Base URI");
                    }
                    context.Namespaces.AddNamespace(prefix, new Uri(uri));
                }
                else if (attr.Name == "xml:base")
                {
                    //Set the Base Uri
                    String baseUri = attr.Value;

                    if (RdfXmlSpecsHelper.IsAbsoluteURI(baseUri))
                    {
                        //Absolute Uri
                        root.BaseUri = baseUri;
                    }
                    else if (!element.BaseUri.Equals(String.Empty))
                    {
                        //Relative Uri with a Base Uri to resolve against
                        //root.BaseUri += baseUri;
                        root.BaseUri = Tools.ResolveUri(baseUri, root.BaseUri);
                    }
                    else
                    {
                        //Relative Uri with no Base Uri
                        throw new RdfParseException("Cannot resolve a Relative Base URI since there is no in-scope Base URI");
                    }
                    element.BaseUri = root.BaseUri;
                }
            }

            #endregion

            //Iterate over Children
            foreach (XmlNode child in docEl.ChildNodes)
            {
                //Ignore Irrelevant Node Types
                if (this.IsIgnorableNode(child))
                {
                    continue;
                }

                //Generate an Event for the Child Node
                ElementEvent childEvent = this.GenerateEvents(context, child, element);
                element.Children.Add(childEvent);
            }

            //Return the Root Event
            return root;
        }