/// <summary>
        /// Performs validation on the xml source as well as evaluates conditional and flow expresions
        /// </summary>
        /// <exception cref=".">For invalid use of conditional expressions or for invalid XML syntax.  If a XmlValidatingReader is passed, then will also throw exceptions for non-schema-conforming xml</exception>
        /// <param name="reader"></param>
        /// <returns>the output xml </returns>
        public string Process(XmlReader reader)
        {
            if(reader == null)
                throw new ArgumentException("Invalid XML reader to pre-process");

            IfContext context = new IfContext(true, true, IfState.None);
            StringWriter xmlText = new StringWriter();
            XmlTextWriter writer = new XmlTextWriter(xmlText);
            writer.Formatting = Formatting.Indented;
            while(reader.Read())
            {
                if(reader.NodeType == XmlNodeType.ProcessingInstruction)
                {
                    bool ignore = false;
                    switch(reader.LocalName)
                    {
                        case "if":
                            m_IfStack.Push(context);
                            context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If);
                            ignore = true;
                            break;

                        case "elseif":
                            if(m_IfStack.Count == 0)
                                throw new WarningException("Unexpected 'elseif' outside of 'if'");
                            else if(context.State != IfState.If && context.State != IfState.ElseIf)
                                throw new WarningException("Unexpected 'elseif' outside of 'if'");

                            context.State = IfState.ElseIf;
                            if(!context.EverKept)
                                context.Keep = ParseExpression(reader.Value);
                            else
                                context.Keep = false;

                            ignore = true;
                            break;

                        case "else":
                            if(m_IfStack.Count == 0)
                                throw new WarningException("Unexpected 'else' outside of 'if'");
                            else if(context.State != IfState.If && context.State != IfState.ElseIf)
                                throw new WarningException("Unexpected 'else' outside of 'if'");

                            context.State = IfState.Else;
                            context.Keep = !context.EverKept;
                            ignore = true;
                            break;

                        case "endif":
                            if(m_IfStack.Count == 0)
                                throw new WarningException("Unexpected 'endif' outside of 'if'");

                            context = (IfContext)m_IfStack.Pop();
                            ignore = true;
                            break;
                    }

                    if(ignore)
                        continue;
                }//end pre-proc instruction

                if(!context.Active || !context.Keep)
                    continue;

                switch(reader.NodeType)
                {
                    case XmlNodeType.Element:
                        bool empty = reader.IsEmptyElement;
                        writer.WriteStartElement(reader.Name);

                        while (reader.MoveToNextAttribute())
                            writer.WriteAttributeString(reader.Name, reader.Value);

                        if(empty)
                            writer.WriteEndElement();

                        break;

                    case XmlNodeType.EndElement:
                        writer.WriteEndElement();
                        break;

                    case XmlNodeType.Text:
                        writer.WriteString(reader.Value);
                        break;

                    case XmlNodeType.CDATA:
                        writer.WriteCData(reader.Value);
                        break;

                    default:
                        break;
                }
            }

            if(m_IfStack.Count != 0)
                throw new WarningException("Mismatched 'if', 'endif' pair");

            return xmlText.ToString();
        }
        /// <summary>
        /// Performs validation on the xml source as well as evaluates conditional and flow expresions
        /// </summary>
        /// <exception cref=".">For invalid use of conditional expressions or for invalid XML syntax.  If a XmlValidatingReader is passed, then will also throw exceptions for non-schema-conforming xml</exception>
        /// <param name="reader"></param>
        /// <returns>the output xml </returns>
        public string Process(XmlReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentException("Invalid XML reader to pre-process");
            }

            IfContext     context = new IfContext(true, true, IfState.None);
            StringWriter  xmlText = new StringWriter();
            XmlTextWriter writer  = new XmlTextWriter(xmlText);

            writer.Formatting = Formatting.Indented;
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.ProcessingInstruction)
                {
                    bool ignore = false;
                    switch (reader.LocalName)
                    {
                    case "if":
                        m_IfStack.Push(context);
                        context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If);
                        ignore  = true;
                        break;

                    case "elseif":
                        if (m_IfStack.Count == 0)
                        {
                            throw new WarningException("Unexpected 'elseif' outside of 'if'");
                        }
                        else if (context.State != IfState.If && context.State != IfState.ElseIf)
                        {
                            throw new WarningException("Unexpected 'elseif' outside of 'if'");
                        }

                        context.State = IfState.ElseIf;
                        if (!context.EverKept)
                        {
                            context.Keep = ParseExpression(reader.Value);
                        }
                        else
                        {
                            context.Keep = false;
                        }

                        ignore = true;
                        break;

                    case "else":
                        if (m_IfStack.Count == 0)
                        {
                            throw new WarningException("Unexpected 'else' outside of 'if'");
                        }
                        else if (context.State != IfState.If && context.State != IfState.ElseIf)
                        {
                            throw new WarningException("Unexpected 'else' outside of 'if'");
                        }

                        context.State = IfState.Else;
                        context.Keep  = !context.EverKept;
                        ignore        = true;
                        break;

                    case "endif":
                        if (m_IfStack.Count == 0)
                        {
                            throw new WarningException("Unexpected 'endif' outside of 'if'");
                        }

                        context = (IfContext)m_IfStack.Pop();
                        ignore  = true;
                        break;
                    }

                    if (ignore)
                    {
                        continue;
                    }
                }                //end pre-proc instruction

                if (!context.Active || !context.Keep)
                {
                    continue;
                }

                switch (reader.NodeType)
                {
                case XmlNodeType.Element:
                    bool empty = reader.IsEmptyElement;
                    writer.WriteStartElement(reader.Name);

                    while (reader.MoveToNextAttribute())
                    {
                        writer.WriteAttributeString(reader.Name, reader.Value);
                    }

                    if (empty)
                    {
                        writer.WriteEndElement();
                    }

                    break;

                case XmlNodeType.EndElement:
                    writer.WriteEndElement();
                    break;

                case XmlNodeType.Text:
                    writer.WriteString(reader.Value);
                    break;

                case XmlNodeType.CDATA:
                    writer.WriteCData(reader.Value);
                    break;

                default:
                    break;
                }
            }

            if (m_IfStack.Count != 0)
            {
                throw new WarningException("Mismatched 'if', 'endif' pair");
            }

            return(xmlText.ToString());
        }