예제 #1
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);
                }
            }
예제 #2
0
            private IList <Token <ModelTokenType> > TransformElement(IStream <Token <MarkupTokenType> > input, bool isStandAlone)
            {
                Token <MarkupTokenType> token = input.Peek();

                DataName elementName = this.DecodeName(token.Name, typeof(Object));
                bool     isVoid      = (token.TokenType == MarkupTokenType.ElementVoid);

                input.Pop();

                IDictionary <DataName, IList <IList <Token <ModelTokenType> > > > children = null;

                while (!input.IsCompleted)
                {
                    token = input.Peek();
                    if (token.TokenType == MarkupTokenType.ElementEnd ||
                        (isVoid && token.TokenType != MarkupTokenType.Attribute))
                    {
                        if (!isVoid)
                        {
                            input.Pop();
                        }

                        List <Token <ModelTokenType> > output = new List <Token <ModelTokenType> >();

                        if ((children == null) ||
                            (children.Count <= 1) ||
                            elementName == XmlInTransformer.DefaultArrayName)
                        {
                            DataName childName = DataName.Empty;
                            IList <IList <Token <ModelTokenType> > > items = null;
                            if (children != null)
                            {
                                // grab the first
                                using (var enumerator = children.GetEnumerator())
                                {
                                    if (enumerator.MoveNext())
                                    {
                                        items     = enumerator.Current.Value;
                                        childName = enumerator.Current.Key;
                                    }
                                }
                            }

                            if ((items != null && items.Count > 1) ||
                                (items == null && elementName == XmlInTransformer.DefaultArrayName) ||
                                childName == XmlInTransformer.DefaultItemName)
                            {
                                // if only child has more than one grandchild
                                // then whole element is acutally an array
                                output.Add(elementName.IsEmpty ? ModelGrammar.TokenArrayBeginUnnamed : ModelGrammar.TokenArrayBegin(this.DecodeName(elementName, typeof(Array))));

                                if (items != null)
                                {
                                    foreach (var item in items)
                                    {
                                        output.AddRange(item);
                                    }
                                }

                                output.Add(ModelGrammar.TokenArrayEnd);
                                return(output);
                            }
                        }

                        if (isStandAlone)
                        {
                            output.Add(elementName.IsEmpty ? ModelGrammar.TokenObjectBeginUnnamed : ModelGrammar.TokenObjectBegin(elementName));
                        }

                        if (children != null)
                        {
                            foreach (var property in children)
                            {
                                if (property.Value.Count == 1)
                                {
                                    if (isStandAlone)
                                    {
                                        // if the parent is a stand alone object then child is a property
                                        DataName name = this.DecodeName(property.Key, typeof(Object));
                                        output.Add(name.IsEmpty ? ModelGrammar.TokenProperty(elementName) : ModelGrammar.TokenProperty(name));
                                    }
                                    output.AddRange(property.Value[0]);
                                    continue;
                                }

                                if (property.Key.IsEmpty)
                                {
                                    // skip mixed content
                                    continue;
                                }

                                // wrap values in array
                                output.Add(property.Key.IsEmpty ? ModelGrammar.TokenArrayBeginUnnamed : ModelGrammar.TokenArrayBegin(this.DecodeName(property.Key, typeof(Array))));
                                foreach (var item in property.Value)
                                {
                                    output.AddRange(item);
                                }
                                output.Add(ModelGrammar.TokenArrayEnd);
                            }
                        }
                        else if (!isStandAlone)
                        {
                            output.Add(ModelGrammar.TokenNull);
                        }

                        if (isStandAlone)
                        {
                            output.Add(ModelGrammar.TokenObjectEnd);
                        }

                        return(output);
                    }

                    DataName propertyName = token.Name;
                    if (token.TokenType == MarkupTokenType.Attribute)
                    {
                        input.Pop();
                    }

                    if (children == null)
                    {
                        children = new Dictionary <DataName, IList <IList <Token <ModelTokenType> > > >();
                    }
                    if (!children.ContainsKey(propertyName))
                    {
                        children[propertyName] = new List <IList <Token <ModelTokenType> > >();
                    }

                    var child = this.TransformValue(input, !isStandAlone);
                    if (child.Count == 1 &&
                        child[0].TokenType == ModelTokenType.Primitive &&
                        child[0].Value != null &&
                        CharUtility.IsNullOrWhiteSpace(child[0].ValueAsString()))
                    {
                        // skip whitespace mixed content
                        continue;
                    }

                    children[propertyName].Add(child);
                }

                throw new TokenException <MarkupTokenType>(
                          token,
                          XmlInTransformer.ErrorUnterminatedObject);
            }