Ejemplo n.º 1
0
            /// <summary>
            /// Parses attributes from the tag using the given
            /// <see cref="ITextParser"/> <paramref name="tp"/>. The
            /// <see cref="ITextParser"/> position should be set to
            /// the first character of the tag following the element name.
            /// </summary>
            private bool ParseAttributes(ITextParser tp)
            {
                const char   kDoubleQuote       = '"';
                const char   kSingleQuote       = '\'';
                const string kDoubleQuoteEntity = "&#22;";

                if (tp.Peek() == '>')
                {
                    tp.MoveAhead();
                    return(true);
                }

                var sb = new StringBuilder();

                // Copy current input character
                void Copy()
                {
                    sb.Append(tp.Peek());
                    tp.MoveAhead();
                }

                // Copy input characters until fence character or end of tag
                void CopyTo(char fence)
                {
                    while (!tp.EndOfText)
                    {
                        var c = tp.Peek();
                        if (c == fence || c == '>')
                        {
                            break;
                        }
                        if (c != kDoubleQuote)
                        {
                            sb.Append(c);
                        }
                        else
                        {
                            sb.Append(kDoubleQuoteEntity);
                        }
                        tp.MoveAhead();
                    }
                }

                // Copy attributes
                var startPos = tp.Position;

                while (!tp.EndOfText)
                {
                    var c = tp.Peek();
                    if (c == '>' || c == '<')
                    {
                        break;
                    }
                    switch (c)
                    {
                    case '=':
                        Copy();
                        c = tp.Peek();
                        if (c == kDoubleQuote)
                        {
                            // Copy double-quoted value
                            Copy();
                            CopyTo(kDoubleQuote);
                            sb.Append(kDoubleQuote);
                            tp.MoveAhead();
                        }
                        else if (c == kSingleQuote)
                        {
                            // Copy single-quoted value, but with double-quotes
                            sb.Append(kDoubleQuote);
                            tp.MoveAhead();
                            CopyTo(kSingleQuote);
                            sb.Append(kDoubleQuote);
                            tp.MoveAhead();
                        }
                        else
                        {
                            // Copy unqouted value adding double-quotes
                            sb.Append(kDoubleQuote);
                            CopyTo(' ');
                            sb.Append(kDoubleQuote);
                        }
                        break;

                    default:
                        Copy();
                        break;
                    }
                }

                if (tp.Peek() != '>')
                {
                    return(false);
                }

                if (tp.CharAt(tp.Position - 1) == '/')
                {
                    IsSelfClosingTag = true;
                    sb.Length        = sb.Length - 1;
                }

                AttributesPart = sb.ToString();
                if (AttributesPart.IndexOf('&') != -1)
                {
                    AttributesPart = ResolveEntities(AttributesPart);
                }

                tp.MoveAhead();

                return(true);
            }