private void WhiteSpace_SeparateStatements(XmlElement contentElement, TSqlFormattingState state)
        {
            if (state.StatementBreakExpected)
            {
                //check whether this is a DECLARE/SET clause with similar precedent, and therefore exempt from double-linebreak.
                XmlElement thisClauseStarter = FirstSemanticElementChild(contentElement);
                if (!(thisClauseStarter != null &&
                      thisClauseStarter.Name.Equals(SqlXmlConstants.ENAME_OTHERKEYWORD) &&
                      state.GetRecentKeyword() != null &&
                      ((thisClauseStarter.InnerXml.ToUpper().Equals("SET") &&
                        state.GetRecentKeyword().Equals("SET")
                        ) ||
                       (thisClauseStarter.InnerXml.ToUpper().Equals("DECLARE") &&
                        state.GetRecentKeyword().Equals("DECLARE")
                       ) ||
                       (thisClauseStarter.InnerXml.ToUpper().Equals("PRINT") &&
                        state.GetRecentKeyword().Equals("PRINT")
                       )
                      )
                      ))
                {
                    state.AddOutputLineBreak();
                }

                state.AddOutputLineBreak();
                state.Indent(state.IndentLevel);
                state.BreakExpected          = false;
                state.SourceBreakPending     = false;
                state.StatementBreakExpected = false;
                state.WordSeparatorExpected  = false;
            }
        }
 public void Assimilate(TSqlFormattingState partialState)
 {
     //TODO: find a way out of the cross-dependent wrapping maze...
     CurrentLineLength     = CurrentLineLength + partialState.CurrentLineLength;
     CurrentLineHasContent = CurrentLineHasContent || partialState.CurrentLineHasContent;
     _outBuilder.Append(partialState.DumpOutput());
 }
 private void ProcessSqlNodeList(XmlNodeList rootList, TSqlFormattingState state)
 {
     foreach (XmlElement contentElement in rootList)
     {
         ProcessSqlNode(contentElement, state);
     }
 }
 //special "we want isolated state, but inheriting existing conditions" constructor
 public TSqlFormattingState(TSqlFormattingState sourceState) : base(sourceState.HtmlOutput)
 {
     IndentLevel  = sourceState.IndentLevel;
     HtmlOutput   = sourceState.HtmlOutput;
     IndentString = sourceState.IndentString;
     IndentLength = sourceState.IndentLength;
     MaxLineWidth = sourceState.MaxLineWidth;
     //TODO: find a way out of the cross-dependent wrapping maze...
     //CurrentLineLength = sourceState.CurrentLineLength;
     CurrentLineLength     = IndentLevel * IndentLength;
     CurrentLineHasContent = sourceState.CurrentLineHasContent;
 }
 private void WhiteSpace_BreakAsExpected(TSqlFormattingState state)
 {
     if (state.BreakExpected)
     {
         state.WhiteSpace_BreakToNextLine();
     }
     if (state.AdditionalBreakExpected)
     {
         state.WhiteSpace_BreakToNextLine();
         state.AdditionalBreakExpected = false;
     }
 }
 private void WhiteSpace_SeparateComment(XmlElement contentElement, TSqlFormattingState state)
 {
     if ((state.BreakExpected || state.WordSeparatorExpected) && state.SourceBreakPending)
     {
         state.BreakExpected = true;
         WhiteSpace_BreakAsExpected(state);
     }
     else if (state.WordSeparatorExpected)
     {
         state.AddOutputSpace();
     }
     state.SourceBreakPending    = false;
     state.WordSeparatorExpected = false;
 }
        public string FormatSQLTree(XmlDocument sqlTreeDoc)
        {
            //thread-safe - each call to FormatSQLTree() gets its own independent state object
            TSqlFormattingState state = new TSqlFormattingState(HTMLColoring, IndentString, SpacesPerTab, MaxLineWidth, 0);

            if (sqlTreeDoc.SelectSingleNode(string.Format("/{0}/@{1}[.=1]", SqlXmlConstants.ENAME_SQL_ROOT, SqlXmlConstants.ANAME_ERRORFOUND)) != null)
            {
                state.AddOutputContent(ErrorOutputPrefix);
            }

            XmlNodeList rootList = sqlTreeDoc.SelectNodes(string.Format("/{0}/*", SqlXmlConstants.ENAME_SQL_ROOT));

            ProcessSqlNodeList(rootList, state);
            WhiteSpace_BreakAsExpected(state);

            return(state.DumpOutput());
        }
 private void WhiteSpace_SeparateWords(TSqlFormattingState state)
 {
     if (state.BreakExpected || state.AdditionalBreakExpected)
     {
         bool wasUnIndent = state.UnIndentInitialBreak;
         if (wasUnIndent)
         {
             state.DecrementIndent();
         }
         WhiteSpace_BreakAsExpected(state);
         if (wasUnIndent)
         {
             state.IncrementIndent();
         }
     }
     else if (state.WordSeparatorExpected)
     {
         state.AddOutputSpace();
     }
     state.UnIndentInitialBreak  = false;
     state.SourceBreakPending    = false;
     state.WordSeparatorExpected = false;
 }
        private void ProcessSqlNode(XmlElement contentElement, TSqlFormattingState state)
        {
            int initialIndent = state.IndentLevel;

            switch (contentElement.Name)
            {
            case SqlXmlConstants.ENAME_SQL_STATEMENT:
                WhiteSpace_SeparateStatements(contentElement, state);
                state.ResetKeywords();
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state);
                state.StatementBreakExpected = true;
                break;

            case SqlXmlConstants.ENAME_SQL_CLAUSE:
                state.UnIndentInitialBreak = true;
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state.IncrementIndent());
                state.DecrementIndent();
                state.BreakExpected = true;
                break;

            case SqlXmlConstants.ENAME_SET_OPERATOR_CLAUSE:
                state.DecrementIndent();
                state.WhiteSpace_BreakToNextLine();     //this is the one already recommended by the start of the clause
                state.WhiteSpace_BreakToNextLine();     //this is the one we additionally want to apply
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state.IncrementIndent());
                state.BreakExpected           = true;
                state.AdditionalBreakExpected = true;
                break;

            case SqlXmlConstants.ENAME_BATCH_SEPARATOR:
                //newline regardless of whether previous element recommended a break or not.
                state.WhiteSpace_BreakToNextLine();
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state);
                state.BreakExpected = true;
                break;

            case SqlXmlConstants.ENAME_DDL_PROCEDURAL_BLOCK:
            case SqlXmlConstants.ENAME_DDL_OTHER_BLOCK:
            case SqlXmlConstants.ENAME_CURSOR_DECLARATION:
            case SqlXmlConstants.ENAME_BEGIN_TRANSACTION:
            case SqlXmlConstants.ENAME_SAVE_TRANSACTION:
            case SqlXmlConstants.ENAME_COMMIT_TRANSACTION:
            case SqlXmlConstants.ENAME_ROLLBACK_TRANSACTION:
            case SqlXmlConstants.ENAME_CONTAINER_OPEN:
            case SqlXmlConstants.ENAME_CONTAINER_CLOSE:
            case SqlXmlConstants.ENAME_WHILE_LOOP:
            case SqlXmlConstants.ENAME_IF_STATEMENT:
            case SqlXmlConstants.ENAME_SELECTIONTARGET:
            case SqlXmlConstants.ENAME_CONTAINER_GENERALCONTENT:
            case SqlXmlConstants.ENAME_CTE_WITH_CLAUSE:
            case SqlXmlConstants.ENAME_PERMISSIONS_BLOCK:
            case SqlXmlConstants.ENAME_PERMISSIONS_DETAIL:
            case SqlXmlConstants.ENAME_MERGE_CLAUSE:
            case SqlXmlConstants.ENAME_MERGE_TARGET:
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state);
                break;

            case SqlXmlConstants.ENAME_CASE_INPUT:
            case SqlXmlConstants.ENAME_BOOLEAN_EXPRESSION:
            case SqlXmlConstants.ENAME_BETWEEN_LOWERBOUND:
            case SqlXmlConstants.ENAME_BETWEEN_UPPERBOUND:
                WhiteSpace_SeparateWords(state);
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state);
                break;

            case SqlXmlConstants.ENAME_CONTAINER_SINGLESTATEMENT:
            case SqlXmlConstants.ENAME_CONTAINER_MULTISTATEMENT:
            case SqlXmlConstants.ENAME_MERGE_ACTION:
                state.BreakExpected = true;
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state);
                state.StatementBreakExpected = false;   //the responsibility for breaking will be with the OUTER statement; there should be no consequence propagating out from statements in this container;
                state.UnIndentInitialBreak   = false;   //if there was no word spacing after the last content statement's clause starter, doesn't mean the unIndent should propagate to the following content!
                break;

            case SqlXmlConstants.ENAME_PERMISSIONS_TARGET:
            case SqlXmlConstants.ENAME_PERMISSIONS_RECIPIENT:
            case SqlXmlConstants.ENAME_DDL_WITH_CLAUSE:
            case SqlXmlConstants.ENAME_MERGE_CONDITION:
            case SqlXmlConstants.ENAME_MERGE_THEN:
                state.BreakExpected        = true;
                state.UnIndentInitialBreak = true;
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state.IncrementIndent());
                state.DecrementIndent();
                break;

            case SqlXmlConstants.ENAME_JOIN_ON_SECTION:
                if (BreakJoinOnSections)
                {
                    state.BreakExpected = true;
                }
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_OPEN), state);
                if (BreakJoinOnSections)
                {
                    state.IncrementIndent();
                }
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_GENERALCONTENT), state);
                if (BreakJoinOnSections)
                {
                    state.DecrementIndent();
                }
                break;

            case SqlXmlConstants.ENAME_CTE_ALIAS:
                state.UnIndentInitialBreak = true;
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state);
                break;

            case SqlXmlConstants.ENAME_ELSE_CLAUSE:
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_OPEN), state.DecrementIndent());
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_SINGLESTATEMENT), state.IncrementIndent());
                break;

            case SqlXmlConstants.ENAME_DDL_AS_BLOCK:
            case SqlXmlConstants.ENAME_CURSOR_FOR_BLOCK:
                state.BreakExpected = true;
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_OPEN), state.DecrementIndent());
                state.BreakExpected = true;
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_GENERALCONTENT), state);
                state.IncrementIndent();
                break;

            case SqlXmlConstants.ENAME_TRIGGER_CONDITION:
                state.DecrementIndent();
                state.WhiteSpace_BreakToNextLine();
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state.IncrementIndent());
                break;

            case SqlXmlConstants.ENAME_CURSOR_FOR_OPTIONS:
            case SqlXmlConstants.ENAME_CTE_AS_BLOCK:
                state.BreakExpected = true;
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_OPEN), state.DecrementIndent());
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_GENERALCONTENT), state.IncrementIndent());
                break;

            case SqlXmlConstants.ENAME_DDL_RETURNS:
            case SqlXmlConstants.ENAME_MERGE_USING:
            case SqlXmlConstants.ENAME_MERGE_WHEN:
                state.BreakExpected        = true;
                state.UnIndentInitialBreak = true;
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state);
                break;

            case SqlXmlConstants.ENAME_BETWEEN_CONDITION:
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_OPEN), state);
                state.IncrementIndent();
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_BETWEEN_LOWERBOUND), state.IncrementIndent());
                if (ExpandBetweenConditions)
                {
                    state.BreakExpected = true;
                }
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_CLOSE), state.DecrementIndent());
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_BETWEEN_UPPERBOUND), state.IncrementIndent());
                state.DecrementIndent();
                state.DecrementIndent();
                break;

            case SqlXmlConstants.ENAME_DDLDETAIL_PARENS:
            case SqlXmlConstants.ENAME_FUNCTION_PARENS:
                //simply process sub-nodes - don't add space or expect any linebreaks (but respect linebreaks if necessary)
                state.WordSeparatorExpected = false;
                WhiteSpace_BreakAsExpected(state);
                state.AddOutputContent(FormatOperator("("), Interfaces.SqlHtmlConstants.CLASS_OPERATOR);
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state.IncrementIndent());
                state.DecrementIndent();
                WhiteSpace_BreakAsExpected(state);
                state.AddOutputContent(FormatOperator(")"), Interfaces.SqlHtmlConstants.CLASS_OPERATOR);
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_DDL_PARENS:
            case SqlXmlConstants.ENAME_EXPRESSION_PARENS:
            case SqlXmlConstants.ENAME_SELECTIONTARGET_PARENS:
                WhiteSpace_SeparateWords(state);
                if (contentElement.Name.Equals(SqlXmlConstants.ENAME_EXPRESSION_PARENS))
                {
                    state.IncrementIndent();
                }
                state.AddOutputContent(FormatOperator("("), Interfaces.SqlHtmlConstants.CLASS_OPERATOR);
                TSqlFormattingState innerState = new TSqlFormattingState(state);
                ProcessSqlNodeList(contentElement.SelectNodes("*"), innerState);
                //if there was a linebreak in the parens content, or if it wanted one to follow, then put linebreaks before and after.
                if (innerState.BreakExpected || innerState.OutputContainsLineBreak)
                {
                    state.WhiteSpace_BreakToNextLine();
                    state.Assimilate(innerState);
                    state.WhiteSpace_BreakToNextLine();
                }
                else
                {
                    state.Assimilate(innerState);
                }
                state.AddOutputContent(FormatOperator(")"), Interfaces.SqlHtmlConstants.CLASS_OPERATOR);
                if (contentElement.Name.Equals(SqlXmlConstants.ENAME_EXPRESSION_PARENS))
                {
                    state.DecrementIndent();
                }
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_BEGIN_END_BLOCK:
            case SqlXmlConstants.ENAME_TRY_BLOCK:
            case SqlXmlConstants.ENAME_CATCH_BLOCK:
                if (contentElement.ParentNode.Name.Equals(SqlXmlConstants.ENAME_SQL_CLAUSE) &&
                    contentElement.ParentNode.ParentNode.Name.Equals(SqlXmlConstants.ENAME_SQL_STATEMENT) &&
                    contentElement.ParentNode.ParentNode.ParentNode.Name.Equals(SqlXmlConstants.ENAME_CONTAINER_SINGLESTATEMENT)
                    )
                {
                    state.DecrementIndent();
                }
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_OPEN), state);
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_MULTISTATEMENT), state);
                state.DecrementIndent();
                state.BreakExpected = true;
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_CLOSE), state);
                state.IncrementIndent();
                if (contentElement.ParentNode.Name.Equals(SqlXmlConstants.ENAME_SQL_CLAUSE) &&
                    contentElement.ParentNode.ParentNode.Name.Equals(SqlXmlConstants.ENAME_SQL_STATEMENT) &&
                    contentElement.ParentNode.ParentNode.ParentNode.Name.Equals(SqlXmlConstants.ENAME_CONTAINER_SINGLESTATEMENT)
                    )
                {
                    state.IncrementIndent();
                }
                break;

            case SqlXmlConstants.ENAME_CASE_STATEMENT:
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_OPEN), state);
                state.IncrementIndent();
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CASE_INPUT), state);
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CASE_WHEN), state);
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CASE_ELSE), state);
                if (ExpandCaseStatements)
                {
                    state.BreakExpected = true;
                }
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_CLOSE), state);
                state.DecrementIndent();
                break;

            case SqlXmlConstants.ENAME_CASE_WHEN:
            case SqlXmlConstants.ENAME_CASE_THEN:
            case SqlXmlConstants.ENAME_CASE_ELSE:
                if (ExpandCaseStatements)
                {
                    state.BreakExpected = true;
                }
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_OPEN), state);
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CONTAINER_GENERALCONTENT), state.IncrementIndent());
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_CASE_THEN), state);
                state.DecrementIndent();
                break;

            case SqlXmlConstants.ENAME_AND_OPERATOR:
            case SqlXmlConstants.ENAME_OR_OPERATOR:
                if (ExpandBooleanExpressions)
                {
                    state.BreakExpected = true;
                }
                ProcessSqlNodeList(contentElement.SelectNodes("*"), state);
                break;

            case SqlXmlConstants.ENAME_COMMENT_MULTILINE:
                WhiteSpace_SeparateComment(contentElement, state);
                state.AddOutputContent("/*" + contentElement.InnerText + "*/", Interfaces.SqlHtmlConstants.CLASS_COMMENT);
                if (contentElement.ParentNode.Name.Equals(SqlXmlConstants.ENAME_SQL_STATEMENT))
                {
                    state.BreakExpected = true;
                }
                else
                {
                    state.WordSeparatorExpected = true;
                }
                break;

            case SqlXmlConstants.ENAME_COMMENT_SINGLELINE:
                WhiteSpace_SeparateComment(contentElement, state);
                state.AddOutputContent("--" + contentElement.InnerText.Replace("\r", "").Replace("\n", ""), Interfaces.SqlHtmlConstants.CLASS_COMMENT);
                state.BreakExpected      = true;
                state.SourceBreakPending = true;
                break;

            case SqlXmlConstants.ENAME_STRING:
            case SqlXmlConstants.ENAME_NSTRING:
                WhiteSpace_SeparateWords(state);
                string outValue = null;
                if (contentElement.Name.Equals(SqlXmlConstants.ENAME_NSTRING))
                {
                    outValue = "N'" + contentElement.InnerText.Replace("'", "''") + "'";
                }
                else
                {
                    outValue = "'" + contentElement.InnerText.Replace("'", "''") + "'";
                }
                state.AddOutputContent(outValue, Interfaces.SqlHtmlConstants.CLASS_STRING);
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_BRACKET_QUOTED_NAME:
                WhiteSpace_SeparateWords(state);
                state.AddOutputContent("[" + contentElement.InnerText.Replace("]", "]]") + "]");
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_QUOTED_STRING:
                WhiteSpace_SeparateWords(state);
                state.AddOutputContent("\"" + contentElement.InnerText.Replace("\"", "\"\"") + "\"");
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_COMMA:
                //comma always ignores requested word spacing
                if (TrailingCommas)
                {
                    state.AddOutputContent(FormatOperator(","), Interfaces.SqlHtmlConstants.CLASS_OPERATOR);

                    if (ExpandCommaLists &&
                        !(contentElement.ParentNode.Name.Equals(SqlXmlConstants.ENAME_DDLDETAIL_PARENS) ||
                          contentElement.ParentNode.Name.Equals(SqlXmlConstants.ENAME_FUNCTION_PARENS)
                          )
                        )
                    {
                        state.BreakExpected = true;
                    }
                    else
                    {
                        state.WordSeparatorExpected = true;
                    }
                }
                else
                {
                    if (ExpandCommaLists &&
                        !(contentElement.ParentNode.Name.Equals(SqlXmlConstants.ENAME_DDLDETAIL_PARENS) ||
                          contentElement.ParentNode.Name.Equals(SqlXmlConstants.ENAME_FUNCTION_PARENS)
                          )
                        )
                    {
                        state.WhiteSpace_BreakToNextLine();
                        state.AddOutputContent(FormatOperator(","), Interfaces.SqlHtmlConstants.CLASS_OPERATOR);
                        if (SpaceAfterExpandedComma)
                        {
                            state.WordSeparatorExpected = true;
                        }
                    }
                    else
                    {
                        WhiteSpace_BreakAsExpected(state);
                        state.AddOutputContent(FormatOperator(","), Interfaces.SqlHtmlConstants.CLASS_OPERATOR);
                        state.WordSeparatorExpected = true;
                    }
                }
                break;

            case SqlXmlConstants.ENAME_PERIOD:
            case SqlXmlConstants.ENAME_SEMICOLON:
            case SqlXmlConstants.ENAME_SCOPERESOLUTIONOPERATOR:
                //always ignores requested word spacing, and doesn't request a following space either.
                state.WordSeparatorExpected = false;
                WhiteSpace_BreakAsExpected(state);
                state.AddOutputContent(FormatOperator(contentElement.InnerText), Interfaces.SqlHtmlConstants.CLASS_OPERATOR);
                break;

            case SqlXmlConstants.ENAME_ASTERISK:
            case SqlXmlConstants.ENAME_OTHEROPERATOR:
                WhiteSpace_SeparateWords(state);
                state.AddOutputContent(FormatOperator(contentElement.InnerText), Interfaces.SqlHtmlConstants.CLASS_OPERATOR);
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_COMPOUNDKEYWORD:
                WhiteSpace_SeparateWords(state);
                state.SetRecentKeyword(contentElement.Attributes[SqlXmlConstants.ANAME_SIMPLETEXT].Value);
                state.AddOutputContent(FormatKeyword(contentElement.Attributes[SqlXmlConstants.ANAME_SIMPLETEXT].Value), Interfaces.SqlHtmlConstants.CLASS_KEYWORD);
                state.WordSeparatorExpected = true;
                ProcessSqlNodeList(contentElement.SelectNodes(SqlXmlConstants.ENAME_COMMENT_MULTILINE + " | " + SqlXmlConstants.ENAME_COMMENT_SINGLELINE), state.IncrementIndent());
                state.DecrementIndent();
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_OTHERKEYWORD:
            case SqlXmlConstants.ENAME_DATATYPE_KEYWORD:
                WhiteSpace_SeparateWords(state);
                state.SetRecentKeyword(contentElement.InnerText);
                state.AddOutputContent(FormatKeyword(contentElement.InnerText), Interfaces.SqlHtmlConstants.CLASS_KEYWORD);
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_PSEUDONAME:
                WhiteSpace_SeparateWords(state);
                state.AddOutputContent(FormatKeyword(contentElement.InnerText), Interfaces.SqlHtmlConstants.CLASS_KEYWORD);
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_FUNCTION_KEYWORD:
                WhiteSpace_SeparateWords(state);
                state.SetRecentKeyword(contentElement.InnerText);
                state.AddOutputContent(contentElement.InnerText, Interfaces.SqlHtmlConstants.CLASS_FUNCTION);
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_OTHERNODE:
            case SqlXmlConstants.ENAME_NUMBER_VALUE:
            case SqlXmlConstants.ENAME_MONETARY_VALUE:
            case SqlXmlConstants.ENAME_BINARY_VALUE:
            case SqlXmlConstants.ENAME_LABEL:
                WhiteSpace_SeparateWords(state);
                state.AddOutputContent(contentElement.InnerText);
                state.WordSeparatorExpected = true;
                break;

            case SqlXmlConstants.ENAME_WHITESPACE:
                //take note if it's a line-breaking space, but don't DO anything here
                if (Regex.IsMatch(contentElement.InnerText, @"(\r|\n)+"))
                {
                    state.SourceBreakPending = true;
                }
                break;

            default:
                throw new Exception("Unrecognized element in SQL Xml!");
            }

            if (initialIndent != state.IndentLevel)
            {
                throw new Exception("Messed up the indenting!! Check code/stack or panic!");
            }
        }