コード例 #1
0
ファイル: XamlXmlReader.cs プロジェクト: Benrnz/Portable.Xaml
        void ProcessAttributesToMember(StartTagInfo sti, XamlType xt)
        {
            foreach (var p in sti.Attributes)
            {
                int    idx    = p.Key.IndexOf(':');
                string prefix = idx > 0 ? p.Key.Substring(0, idx) : String.Empty;
                string name   = idx > 0 ? p.Key.Substring(idx + 1) : p.Key;

                var am = FindAttachableMember(prefix, name);
                if (am != null)
                {
                    sti.Members.Add(new Pair(am, p.Value));
                    continue;
                }
                var xm = xt.GetMember(name);
                if (xm != null)
                {
                    sti.Members.Add(new Pair(xm, p.Value));
                }
                // ignore unknown attribute
            }
        }
コード例 #2
0
ファイル: XamlXmlReader.cs プロジェクト: Benrnz/Portable.Xaml
        // member element, implicit member, children via content property, or value
        IEnumerable <XamlXmlNodeInfo> ReadMemberElement(XamlType parentType, XamlType xt)
        {
            XamlMember xm       = null;
            var        name     = r.LocalName;
            int        idx      = name.IndexOf('.');
            string     typeName = null;

            if (idx >= 0)
            {
                typeName = name.Substring(0, idx);
                name     = name.Substring(idx + 1);
                // check if it is an attachable member first, either of this type or another type
                // Should this also check the namespace to find the correct type?
                if (typeName == xt.GetInternalXmlName())
                {
                    xm = xt.GetMember(name);
                }
                else
                {
                    xm = FindAttachableMember(r.Prefix, typeName, name);
                }
            }
            else
            {
                xm = (XamlMember)FindStandardDirective(name, AllowedMemberLocations.MemberElement);
                if (xm == null)
                {
                    // still not? could it be omitted as content property or items ?
                    if ((xm = GetExtraMember(xt)) != null)
                    {
                        // Note that this does not involve r.Read()
                        foreach (var ni in ReadMember(xt, xm))
                        {
                            yield return(ni);
                        }
                        yield break;
                    }
                }
            }
            if (xm == null)
            {
                // Current element could be for another member in the parent type (if exists)
                if (parentType != null &&
                    typeName != null &&
                    typeName == parentType.GetInternalXmlName() &&
                    parentType.GetMember(name) != null)
                {
                    // stop the iteration and signal the caller to not read current element as an object. (It resolves conflicts between "start object for current collection's item" and "start member for the next member in the parent object".
                    yield return(Node(XamlNodeType.None, null));

                    yield break;
                }

                // ok, then create unknown member.
                xm = new XamlMember(name, xt, false);                  // FIXME: not sure if isAttachable is always false.
            }

            if (!r.IsEmptyElement)
            {
                r.Read();
                foreach (var ni in ReadMember(xt, xm))
                {
                    yield return(ni);
                }
                r.MoveToContent();
                r.ReadEndElement();
            }
            else
            {
                r.Read();
            }
        }
コード例 #3
0
ファイル: XamlXmlReader.cs プロジェクト: cm4ker/Portable.Xaml
        // Note that it could return invalid (None) node to tell the caller that it is not really an object element.
        IEnumerable <XamlXmlNodeInfo> ReadObjectElement(XamlType parentType, XamlMember currentMember)
        {
            if (r.NodeType == XmlNodeType.EndElement)
            {
                yield break;
            }

            if (r.NodeType == XmlNodeType.Text || r.NodeType == XmlNodeType.CDATA)
            {
                yield return(Node(XamlNodeType.Value, NormalizeWhitespace(r.Value)));

                r.Read();
                yield break;
            }

            if (r.NodeType != XmlNodeType.Element)
            {
                throw new XamlParseException(String.Format("Element is expected, but got {0}", r.NodeType));
            }

            if (r.MoveToFirstAttribute())
            {
                do
                {
                    if (r.NamespaceURI == XamlLanguage.Xmlns2000Namespace)
                    {
                        yield return(Node(XamlNodeType.NamespaceDeclaration, new NamespaceDeclaration(ResolveLocalNamespace(r.Value), r.Prefix == "xmlns" ? r.LocalName : String.Empty)));
                    }
                } while (r.MoveToNextAttribute());
                r.MoveToElement();
            }

            var sti = GetStartTagInfo();

            var xt = sctx.GetXamlType(sti.TypeName);

            if (ReferenceEquals(xt, null))
            {
                // Current element could be for another member in the parent type (if exists)
                if (parentType != null && (r.LocalName.IndexOf('.') > 0 || parentType.GetMember(r.LocalName) != null))
                {
                    // stop the iteration and signal the caller to not read current element as an object. (It resolves conflicts between "start object for current collection's item" and "start member for the next member in the parent object".
                    yield return(Node(XamlNodeType.None, null));

                    yield break;
                }

                // creates name-only XamlType. Also, it does not seem that it does not store this XamlType to XamlSchemaContext (Try GetXamlType(xtn) after reading such xaml node, it will return null).
                xt = new XamlType(sti.Namespace, sti.Name, sti.TypeName.TypeArguments?.Select(xxtn => sctx.GetXamlType(xxtn)).ToArray(), sctx);
            }

            // It could still be GetObject if current_member is not defer-loaded, it
            // is not a directive, and current type is not
            // a markup extension.
            // (I'm not very sure about the condition;
            // it could be more complex.)
            // seealso: bug #682131
            if (!ReferenceEquals(currentMember, null) &&
                ReferenceEquals(currentMember.DeferringLoader, null) &&
                !xt.CanAssignTo(currentMember.Type) &&
                !ReferenceEquals(xt, XamlLanguage.Reference) &&
                (
                    currentMember.DeclaringType?.ContentProperty == currentMember ||
                    (!currentMember.IsDirective && !xt.IsMarkupExtension)
                )
                )
            {
                yield return(Node(XamlNodeType.GetObject, currentMember.Type));

                foreach (var ni in ReadMembers(parentType, currentMember.Type))
                {
                    yield return(ni);
                }
                yield return(Node(XamlNodeType.EndObject, currentMember.Type));

                yield break;
            }


            yield return(Node(XamlNodeType.StartObject, xt));

            // process attribute members (including MarkupExtensions)
            ProcessAttributesToMember(sti, xt);

            for (int i = 0; i < sti.Members.Count; i++)
            {
                var pair = sti.Members[i];
                yield return(Node(XamlNodeType.StartMember, pair.Key));

                // Try markup extension
                // FIXME: is this rule correct?
                var v = pair.Value;
                if (!string.IsNullOrEmpty(v) && v[0] == '{')
                {
                    if (v.Length >= 2 && v[1] == '}')
                    {
                        // escaped value with {} at the beginning of the string
                        yield return(Node(XamlNodeType.Value, v.Substring(2)));
                    }
                    else
                    {
                        var pai = new ParsedMarkupExtensionInfo(v, xaml_namespace_resolver, sctx);
                        pai.Parse();
                        foreach (var node in ReadMarkup(pai))
                        {
                            yield return(node);
                        }
                    }
                }
                else
                {
                    yield return(Node(XamlNodeType.Value, v));
                }

                yield return(Node(XamlNodeType.EndMember, pair.Key));
            }

            // process content members
            if (!r.IsEmptyElement)
            {
                r.Read();
                foreach (var ni in ReadMembers(parentType, xt))
                {
                    yield return(ni);
                }
                r.ReadEndElement();
            }
            else
            {
                r.Read();                  // consume empty element.
            }
            yield return(Node(XamlNodeType.EndObject, xt));
        }
コード例 #4
0
ファイル: XamlXmlReader.cs プロジェクト: Benrnz/Portable.Xaml
        // Note that it could return invalid (None) node to tell the caller that it is not really an object element.
        IEnumerable <XamlXmlNodeInfo> ReadObjectElement(XamlType parentType, XamlMember currentMember)
        {
            if (r.NodeType == XmlNodeType.EndElement)
            {
                yield break;
            }

            if (r.NodeType == XmlNodeType.Text || r.NodeType == XmlNodeType.CDATA)
            {
                //throw new XamlParseException (String.Format ("Element is expected, but got {0}", r.NodeType));
                yield return(Node(XamlNodeType.Value, r.Value));

                r.Read();
                yield break;
            }

            if (r.NodeType != XmlNodeType.Element)
            {
                throw new XamlParseException(String.Format("Element is expected, but got {0}", r.NodeType));
            }

            if (r.MoveToFirstAttribute())
            {
                do
                {
                    if (r.NamespaceURI == XamlLanguage.Xmlns2000Namespace)
                    {
                        yield return(Node(XamlNodeType.NamespaceDeclaration, new NamespaceDeclaration(r.Value, r.Prefix == "xmlns" ? r.LocalName : String.Empty)));
                    }
                } while (r.MoveToNextAttribute());
                r.MoveToElement();
            }

            var sti = GetStartTagInfo();

            var xt = sctx.GetXamlType(sti.TypeName);

            if (xt == null)
            {
                // Current element could be for another member in the parent type (if exists)
                if (parentType != null && (r.LocalName.IndexOf('.') > 0 || parentType.GetMember(r.LocalName) != null))
                {
                    // stop the iteration and signal the caller to not read current element as an object. (It resolves conflicts between "start object for current collection's item" and "start member for the next member in the parent object".
                    yield return(Node(XamlNodeType.None, null));

                    yield break;
                }

                // creates name-only XamlType. Also, it does not seem that it does not store this XamlType to XamlSchemaContext (Try GetXamlType(xtn) after reading such xaml node, it will return null).
                xt = new XamlType(sti.Namespace, sti.Name, sti.TypeName.TypeArguments == null ? null : sti.TypeName.TypeArguments.Select <XamlTypeName, XamlType> (xxtn => sctx.GetXamlType(xxtn)).ToArray(), sctx);
            }

            bool isGetObject = false;

            if (currentMember != null && !xt.CanAssignTo(currentMember.Type))
            {
                if (currentMember.DeclaringType != null && currentMember.DeclaringType.ContentProperty == currentMember)
                {
                    isGetObject = true;
                }

                // It could still be GetObject if current_member
                // is not a directive and current type is not
                // a markup extension.
                // (I'm not very sure about the condition;
                // it could be more complex.)
                // seealso: bug #682131
                else if (!(currentMember is XamlDirective) &&
                         !xt.IsMarkupExtension)
                {
                    isGetObject = true;
                }
            }

            if (isGetObject)
            {
                yield return(Node(XamlNodeType.GetObject, currentMember.Type));

                foreach (var ni in ReadMembers(parentType, currentMember.Type))
                {
                    yield return(ni);
                }
                yield return(Node(XamlNodeType.EndObject, currentMember.Type));

                yield break;
            }
            // else

            yield return(Node(XamlNodeType.StartObject, xt));

            // process attribute members (including MarkupExtensions)
            ProcessAttributesToMember(sti, xt);

            foreach (var pair in sti.Members)
            {
                yield return(Node(XamlNodeType.StartMember, pair.Key));

                // Try markup extension
                // FIXME: is this rule correct?
                var v = pair.Value;
                if (!String.IsNullOrEmpty(v) && v [0] == '{')
                {
                    var pai = ParsedMarkupExtensionInfo.Parse(v, xaml_namespace_resolver, sctx);
                    yield return(Node(XamlNodeType.StartObject, pai.Type));

                    foreach (var xepair in pai.Arguments)
                    {
                        yield return(Node(XamlNodeType.StartMember, xepair.Key));

                        if (xepair.Value is List <string> )
                        {
                            foreach (var s in (List <string>)xepair.Value)
                            {
                                yield return(Node(XamlNodeType.Value, s));
                            }
                        }
                        else
                        {
                            yield return(Node(XamlNodeType.Value, xepair.Value));
                        }
                        yield return(Node(XamlNodeType.EndMember, xepair.Key));
                    }
                    yield return(Node(XamlNodeType.EndObject, pai.Type));
                }
                else
                {
                    yield return(Node(XamlNodeType.Value, pair.Value));
                }

                yield return(Node(XamlNodeType.EndMember, pair.Key));
            }

            // process content members
            if (!r.IsEmptyElement)
            {
                r.Read();
                foreach (var ni in ReadMembers(parentType, xt))
                {
                    yield return(ni);
                }
                r.ReadEndElement();
            }
            else
            {
                r.Read();                  // consume empty element.
            }
            yield return(Node(XamlNodeType.EndObject, xt));
        }
コード例 #5
0
        IEnumerable <XamlXmlNodeInfo> ReadCollectionItems(XamlType parentType, XamlMember xm)
        {
            bool GetNextElementTrim()
            {
                if (r.NodeType == XmlNodeType.Element)
                {
                    var sti = GetStartTagInfo();
                    var xt  = sctx.GetXamlType(sti.TypeName);
                    return(xt.TrimSurroundingWhitespace);
                }

                return(true);
            }

            XamlTypeName previous = null;

            r.MoveToContent();

            while (r.NodeType != XmlNodeType.EndElement)
            {
                switch (r.NodeType)
                {
                case XmlNodeType.Text:
                    var text = r.Value;
                    r.Read();

                    var trimStart = previous == null ||
                                    sctx.GetXamlType(previous).TrimSurroundingWhitespace;
                    var trimEnd = r.NodeType == XmlNodeType.EndElement ||
                                  GetNextElementTrim();

                    yield return(Node(XamlNodeType.Value, NormalizeWhitespace(text, trimStart, trimEnd)));

                    break;

                case XmlNodeType.Element:
                    if (parentType != null && (r.LocalName.IndexOf('.') > 0 || parentType.GetMember(r.LocalName) != null))
                    {
                        yield return(Node(XamlNodeType.None, null));

                        yield break;
                    }

                    var sti = GetStartTagInfo();
                    previous = sti.TypeName;

                    foreach (var x in ReadObjectElement(parentType, xm))
                    {
                        yield return(x);
                    }
                    break;

                case XmlNodeType.Whitespace:
                    r.Read();
                    if (previous != null &&
                        parentType.IsWhitespaceSignificantCollection &&
                        !sctx.GetXamlType(previous).TrimSurroundingWhitespace)
                    {
                        if (r.NodeType != XmlNodeType.EndElement)
                        {
                            yield return(Node(XamlNodeType.Value, " "));
                        }
                    }
                    break;

                default:
                    throw new XamlParseException(String.Format("Text or Element is expected, but got {0}", r.NodeType));
                }
            }
        }