Exemplo n.º 1
0
            private void EmitTag(List <Token <MarkupTokenType> > output, DataName elementName, IDictionary <DataName, Token <ModelTokenType> > attributes, MarkupTokenType tagType)
            {
                if (this.pendingNewLine)
                {
                    if (this.Settings.PrettyPrint)
                    {
                        this.depth++;
                        this.EmitNewLine(output);
                    }
                    this.pendingNewLine = false;
                }

                PrefixScopeChain.Scope scope = new PrefixScopeChain.Scope();
                scope.TagName = elementName;

                if (!this.ScopeChain.ContainsNamespace(elementName.NamespaceUri))
                {
                    scope[elementName.Prefix] = elementName.NamespaceUri;
                }
                this.ScopeChain.Push(scope);

                switch (tagType)
                {
                case MarkupTokenType.ElementVoid:
                {
                    output.Add(MarkupGrammar.TokenElementVoid(elementName));
                    break;
                }

                case MarkupTokenType.ElementEnd:
                {
                    output.Add(MarkupGrammar.TokenElementEnd);
                    break;
                }

                default:
                case MarkupTokenType.ElementBegin:
                {
                    output.Add(MarkupGrammar.TokenElementBegin(elementName));
                    break;
                }
                }

                if (attributes != null)
                {
                    foreach (var attr in attributes)
                    {
                        output.Add(MarkupGrammar.TokenAttribute(attr.Key));
                        output.Add(attr.Value.ChangeType(MarkupTokenType.Primitive));
                    }

                    attributes.Clear();
                }
            }
Exemplo n.º 2
0
        private void WriteTag(
            TextWriter writer,
            MarkupTokenType type,
            DataName tagName,
            IDictionary <DataName, Token <MarkupTokenType> > attributes,
            PrefixScopeChain.Scope prefixDeclarations)
        {
            if (String.IsNullOrEmpty(tagName.LocalName))
            {
                // represents a document fragment
                return;
            }

            string tagPrefix = this.ScopeChain.EnsurePrefix(tagName.Prefix, tagName.NamespaceUri) ?? tagName.Prefix;

            // "<"
            writer.Write(MarkupGrammar.OperatorElementBegin);
            if (type == MarkupTokenType.ElementEnd)
            {
                // "/"
                writer.Write(MarkupGrammar.OperatorElementClose);
            }

            if (!String.IsNullOrEmpty(tagPrefix))
            {
                // "prefix:"
                this.WriteLocalName(writer, tagPrefix);
                writer.Write(MarkupGrammar.OperatorPrefixDelim);
            }
            // "local-name"
            this.WriteLocalName(writer, tagName.LocalName);

            // emit all namespaces first, sorted by prefix
            if (prefixDeclarations != null)
            {
                foreach (var declaration in prefixDeclarations)
                {
                    this.WriteXmlns(writer, declaration.Key, declaration.Value);
                }
            }

            if (attributes != null)
            {
                foreach (var attribute in attributes)
                {
                    // Not sure if this is correct: http://stackoverflow.com/questions/3312390
                    // "The namespace name for an unprefixed attribute name always has no value"
                    // "The attribute value in a default namespace declaration MAY be empty.
                    // This has the same effect, within the scope of the declaration, of there being no default namespace."
                    // http://www.w3.org/TR/xml-names/#defaulting
                    string attrPrefix = this.ScopeChain.EnsurePrefix(attribute.Key.Prefix, attribute.Key.NamespaceUri) ?? attribute.Key.Prefix;

                    this.WriteAttribute(writer, attrPrefix, attribute.Key.LocalName, attribute.Value);
                }
            }

            if (!this.canonicalForm &&
                type == MarkupTokenType.ElementVoid)
            {
                // " /"
                writer.Write(MarkupGrammar.OperatorValueDelim);
                writer.Write(MarkupGrammar.OperatorElementClose);
            }
            // ">"
            writer.Write(MarkupGrammar.OperatorElementEnd);

            if (this.canonicalForm &&
                type == MarkupTokenType.ElementVoid)
            {
                // http://www.w3.org/TR/xml-c14n#Terminology
                this.WriteTag(writer, MarkupTokenType.ElementEnd, tagName, null, null);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Formats the token sequence to the writer
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="tokens"></param>
        public void Format(IEnumerable <Token <MarkupTokenType> > tokens, TextWriter writer)
        {
            if (tokens == null)
            {
                throw new ArgumentNullException("tokens");
            }

            IStream <Token <MarkupTokenType> > stream = Stream <Token <MarkupTokenType> > .Create(tokens);

            PrefixScopeChain.Scope scope = null;
            while (!stream.IsCompleted)
            {
                Token <MarkupTokenType> token = stream.Peek();
                switch (token.TokenType)
                {
                case MarkupTokenType.ElementBegin:
                case MarkupTokenType.ElementVoid:
                {
                    DataName        tagName = token.Name;
                    MarkupTokenType tagType = token.TokenType;

                    stream.Pop();
                    token = stream.Peek();

                    scope = new PrefixScopeChain.Scope();

                    if (this.ScopeChain.ContainsNamespace(tagName.NamespaceUri) ||
                        (String.IsNullOrEmpty(tagName.NamespaceUri) && !this.ScopeChain.ContainsPrefix(String.Empty)))
                    {
                        string prefix = this.ScopeChain.GetPrefix(tagName.NamespaceUri, false);
                        scope.TagName = new DataName(tagName.LocalName, prefix, tagName.NamespaceUri);
                    }
                    else
                    {
                        scope[tagName.Prefix] = tagName.NamespaceUri;
                        scope.TagName         = tagName;
                    }

                    this.ScopeChain.Push(scope);

                    IDictionary <DataName, Token <MarkupTokenType> > attributes = null;
                    while (!stream.IsCompleted && token.TokenType == MarkupTokenType.Attribute)
                    {
                        if (attributes == null)
                        {
                            attributes = this.canonicalForm ?
                                         (IDictionary <DataName, Token <MarkupTokenType> >) new CanonicalList() :
                                         (IDictionary <DataName, Token <MarkupTokenType> >) new Dictionary <DataName, Token <MarkupTokenType> >();
                        }
                        DataName attrName = token.Name;

                        string prefix = this.ScopeChain.EnsurePrefix(attrName.Prefix, attrName.NamespaceUri);
                        if (prefix != null)
                        {
                            if (prefix != attrName.Prefix)
                            {
                                attrName = new DataName(attrName.LocalName, prefix, attrName.NamespaceUri, true);
                            }

                            if (!this.ScopeChain.ContainsNamespace(attrName.NamespaceUri) &&
                                (!String.IsNullOrEmpty(attrName.NamespaceUri) || this.ScopeChain.ContainsPrefix(String.Empty)))
                            {
                                scope[prefix] = attrName.NamespaceUri;
                            }
                        }

                        stream.Pop();
                        token = stream.Peek();

                        attributes[attrName] = token ?? MarkupGrammar.TokenNone;

                        stream.Pop();
                        token = stream.Peek();
                    }

                    this.WriteTag(writer, tagType, tagName, attributes, scope);

                    scope = null;
                    break;
                }

                case MarkupTokenType.ElementEnd:
                {
                    if (this.ScopeChain.HasScope)
                    {
                        this.WriteTag(writer, MarkupTokenType.ElementEnd, this.ScopeChain.Peek().TagName, null, null);
                        this.ScopeChain.Pop();
                    }
                    else
                    {
                        // TODO: decide if this is should throw an exception
                    }

                    stream.Pop();
                    token = stream.Peek();
                    break;
                }

                case MarkupTokenType.Primitive:
                {
                    ITextFormattable <MarkupTokenType> formattable = token.Value as ITextFormattable <MarkupTokenType>;
                    if (formattable != null)
                    {
                        formattable.Format(this, writer);
                    }
                    else
                    {
                        HtmlFormatter.HtmlEncode(writer, token.ValueAsString(), this.encodeNonAscii, this.canonicalForm);
                    }

                    stream.Pop();
                    token = stream.Peek();
                    break;
                }

                default:
                {
                    throw new TokenException <MarkupTokenType>(
                              token,
                              String.Format(ErrorUnexpectedToken, token.TokenType));
                }
                }
            }
        }
Exemplo n.º 4
0
            /// <summary>
            /// Consumes a sequence of tokens and produces a token sequence of a different type
            /// </summary>
            public IEnumerable <Token <ModelTokenType> > Transform(IEnumerable <Token <MarkupTokenType> > input)
            {
                if (input == null)
                {
                    throw new ArgumentNullException("input");
                }

                IStream <Token <MarkupTokenType> > stream = Stream <Token <MarkupTokenType> > .Create(input);

                PrefixScopeChain scopeChain = new PrefixScopeChain();

                Token <MarkupTokenType> token = stream.Peek();

                while (!stream.IsCompleted)
                {
                    switch (token.TokenType)
                    {
                    case MarkupTokenType.ElementBegin:
                    case MarkupTokenType.ElementVoid:
                    {
                        bool hasProperties = false;
                        bool isVoid        = (token.TokenType == MarkupTokenType.ElementVoid);

                        DataName tagName = token.Name;
                        yield return(ModelGrammar.TokenArrayBeginUnnamed);

                        // NOTE: JSON doesn't support namespaces so resolve the name to prefix+':'+local-name
                        yield return(ModelGrammar.TokenPrimitive(tagName.ToPrefixedName()));

                        PrefixScopeChain.Scope scope = new PrefixScopeChain.Scope();
                        string prefix = scopeChain.GetPrefix(tagName.NamespaceUri, false);
                        if (!StringComparer.Ordinal.Equals(prefix, tagName.Prefix) &&
                            !String.IsNullOrEmpty(tagName.NamespaceUri))
                        {
                            scope[tagName.Prefix] = tagName.NamespaceUri;

                            // new namespace scope so need to emit xmlns
                            hasProperties = true;
                            yield return(ModelGrammar.TokenObjectBeginUnnamed);
                        }
                        scope.TagName = tagName;
                        scopeChain.Push(scope);

                        stream.Pop();
                        token = stream.Peek();
                        while (!stream.IsCompleted &&
                               token.TokenType == MarkupTokenType.Attribute)
                        {
                            if (!hasProperties)
                            {
                                hasProperties = true;
                                yield return(ModelGrammar.TokenObjectBeginUnnamed);
                            }

                            DataName attrName = token.Name;

                            prefix = scopeChain.GetPrefix(attrName.NamespaceUri, false);
                            if (!StringComparer.Ordinal.Equals(prefix, attrName.Prefix) &&
                                !String.IsNullOrEmpty(attrName.NamespaceUri))
                            {
                                scope[attrName.Prefix] = attrName.NamespaceUri;
                            }

                            // NOTE: JSON doesn't support namespaces so resolve the name to prefix+':'+local-name
                            yield return(ModelGrammar.TokenProperty(new DataName(attrName.ToPrefixedName())));

                            stream.Pop();
                            token = stream.Peek();

                            switch (token.TokenType)
                            {
                            case MarkupTokenType.Primitive:
                            {
                                yield return(token.ChangeType(ModelTokenType.Primitive));

                                break;
                            }

                            default:
                            {
                                throw new TokenException <MarkupTokenType>(
                                          token,
                                          String.Format(ErrorUnexpectedToken, token.TokenType));
                            }
                            }

                            stream.Pop();
                            token = stream.Peek();
                        }

                        if (hasProperties)
                        {
                            foreach (var xmlns in scope)
                            {
                                if (String.IsNullOrEmpty(xmlns.Key))
                                {
                                    yield return(ModelGrammar.TokenProperty("xmlns"));
                                }
                                else
                                {
                                    yield return(ModelGrammar.TokenProperty(String.Concat("xmlns:", xmlns.Key)));
                                }
                                yield return(ModelGrammar.TokenPrimitive(xmlns.Value));
                            }

                            yield return(ModelGrammar.TokenObjectEnd);
                        }

                        if (isVoid)
                        {
                            yield return(ModelGrammar.TokenArrayEnd);

                            scopeChain.Pop();
                        }
                        break;
                    }

                    case MarkupTokenType.ElementEnd:
                    {
                        if (scopeChain.Count > 0)
                        {
                            yield return(ModelGrammar.TokenArrayEnd);
                        }
                        scopeChain.Pop();

                        stream.Pop();
                        token = stream.Peek();
                        break;
                    }

                    case MarkupTokenType.Primitive:
                    {
                        if (token.Value is ITextFormattable <ModelTokenType> ||
                            token.Value is ITextFormattable <MarkupTokenType> )
                        {
                            yield return(token.ChangeType(ModelTokenType.Primitive));

                            stream.Pop();
                            token = stream.Peek();
                            break;
                        }

                        string value = token.ValueAsString();

                        stream.Pop();
                        token = stream.Peek();
                        while (!stream.IsCompleted &&
                               (token.TokenType == MarkupTokenType.Primitive) &&
                               !(token.Value is ITextFormattable <ModelTokenType>) &&
                               !(token.Value is ITextFormattable <MarkupTokenType>))
                        {
                            // concatenate adjacent value nodes
                            value = String.Concat(value, token.ValueAsString());

                            stream.Pop();
                            token = stream.Peek();
                        }

                        switch (this.Whitespace)
                        {
                        case WhitespaceType.Normalize:
                        {
                            // replace whitespace chunks with single space (HTML-style normalization)
                            value = JsonMLInTransformer.RegexWhitespace.Replace(value, JsonMLInTransformer.SingleSpace);
                            goto default;
                        }

                        case WhitespaceType.None:
                        {
                            if (CharUtility.IsNullOrWhiteSpace(value))
                            {
                                break;
                            }
                            goto default;
                        }

                        case WhitespaceType.Preserve:
                        default:
                        {
                            yield return(ModelGrammar.TokenPrimitive(value));

                            break;
                        }
                        }
                        break;
                    }

                    case MarkupTokenType.Attribute:
                    default:
                    {
                        throw new TokenException <MarkupTokenType>(
                                  token,
                                  String.Format(ErrorUnexpectedToken, token.TokenType));
                    }
                    }
                }

                while (scopeChain.Count > 0)
                {
                    scopeChain.Pop();
                    yield return(ModelGrammar.TokenArrayEnd);
                }
            }