void WriteAnyElementContent(XmlTypeMapMemberAnyElement member, object memberValue)
        {
            //
            // XmlAnyElement can be of XmlElement or XmlNode type
            //
            if (member.TypeData.Type == typeof(XmlElement) || member.TypeData.Type == typeof(XmlNode))
            {
                memberValue = new object[] { memberValue };
            }

            Array elems = (Array)memberValue;

            foreach (var elem_ in elems)
            {
                XmlNode elem = elem_ as XmlNode;
                if (elem == null)
                {
                    throw new InvalidOperationException(String.Format("XmlAnyElementAttribute can only be applied to members of type XmlElement, XmlElement[] or XmlNode[]. The target object is {0}", elem_ != null ? elem_.GetType() : null));
                }
                if (elem is XmlElement)
                {
                    if (member.IsElementDefined(elem.Name, elem.NamespaceURI))
                    {
                        if (_format == SerializationFormat.Literal)
                        {
                            WriteElementLiteral(elem, "", "", false, true);
                        }
                        else
                        {
                            WriteElementEncoded(elem, "", "", false, true);
                        }
                    }
                    else
                    {
                        throw CreateUnknownAnyElementException(elem.Name, elem.NamespaceURI);
                    }
                }
                else
                {
                    elem.WriteTo(Writer);
                }
            }
        }
Ejemplo n.º 2
0
        internal XmlMemberMapping(string memberName, string defaultNamespace, XmlTypeMapMember mapMem, bool encodedFormat)
        {
            _mapMember  = mapMem;
            _memberName = memberName;

            if (mapMem is XmlTypeMapMemberAnyElement)
            {
                XmlTypeMapMemberAnyElement anyelem = (XmlTypeMapMemberAnyElement)mapMem;
                XmlTypeMapElementInfo      info    = (XmlTypeMapElementInfo)anyelem.ElementInfo[anyelem.ElementInfo.Count - 1];
                _elementName = info.ElementName;
                _namespace   = info.Namespace;
                if (info.MappedType != null)
                {
                    _typeNamespace = info.MappedType.Namespace;
                }
                else
                {
                    _typeNamespace = "";
                }
            }
            else if (mapMem is XmlTypeMapMemberElement)
            {
                XmlTypeMapElementInfo info = (XmlTypeMapElementInfo)((XmlTypeMapMemberElement)mapMem).ElementInfo[0];
                _elementName = info.ElementName;
                if (encodedFormat)
                {
                    _namespace = defaultNamespace;
                    if (info.MappedType != null)
                    {
                        _typeNamespace = "";
                    }
                    else
                    {
                        _typeNamespace = info.DataTypeNamespace;
                    }
                }
                else
                {
                    _namespace = info.Namespace;
                    if (info.MappedType != null)
                    {
                        _typeNamespace = info.MappedType.Namespace;
                    }
                    else
                    {
                        _typeNamespace = "";
                    }
                    _form = info.Form;
                }
            }
            else
            {
                _elementName = _memberName;
                _namespace   = "";
            }

            if (_form == XmlSchemaForm.None)
            {
                _form = XmlSchemaForm.Qualified;
            }
        }
        void ReadMembers(ClassMap map, object ob, bool isValueList, bool readBySoapOrder)
        {
            // Reads attributes
            ReadAttributeMembers(map, ob, isValueList);

            if (!isValueList)
            {
                Reader.MoveToElement();
                if (Reader.IsEmptyElement)
                {
                    SetListMembersDefaults(map, ob, isValueList);
                    return;
                }

                Reader.ReadStartElement();
            }

            // Reads elements

            bool[] readFlag = new bool[(map.ElementMembers != null) ? map.ElementMembers.Count : 0];

            bool hasAnyReturnMember = (isValueList && _format == SerializationFormat.Encoded && map.ReturnMember != null);

            Reader.MoveToContent();

            int[]    indexes          = null;
            object[] flatLists        = null;
            object[] flatListsChoices = null;
            Fixup    fixup            = null;
            int      ind = -1;
            int      maxInd;

            if (readBySoapOrder)
            {
                if (map.ElementMembers != null)
                {
                    maxInd = map.ElementMembers.Count;
                }
                else
                {
                    maxInd = -1;
                }
            }
            else
            {
                maxInd = int.MaxValue;
            }

            if (map.FlatLists != null)
            {
                indexes   = new int[map.FlatLists.Count];
                flatLists = new object[map.FlatLists.Count];
                foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
                {
                    if (IsReadOnly(mem, mem.TypeData, ob, isValueList))
                    {
                        flatLists [mem.FlatArrayIndex] = mem.GetValue(ob);
                    }
                    else if (mem.TypeData.Type.IsArray)
                    {
                        flatLists [mem.FlatArrayIndex] = InitializeList(mem.TypeData);
                    }
                    else
                    {
                        object list = mem.GetValue(ob);
                        if (list == null)
                        {
                            list = InitializeList(mem.TypeData);
                            SetMemberValue(mem, ob, list, isValueList);
                        }
                        flatLists [mem.FlatArrayIndex] = list;
                    }

                    if (mem.ChoiceMember != null)
                    {
                        if (flatListsChoices == null)
                        {
                            flatListsChoices = new object [map.FlatLists.Count];
                        }
                        flatListsChoices [mem.FlatArrayIndex] = InitializeList(mem.ChoiceTypeData);
                    }
                }
            }

            if (_format == SerializationFormat.Encoded && map.ElementMembers != null)
            {
                FixupCallbackInfo info = new FixupCallbackInfo(this, map, isValueList);
                fixup = new Fixup(ob, new XmlSerializationFixupCallback(info.FixupMembers), map.ElementMembers.Count);
                AddFixup(fixup);
            }

            XmlTypeMapMember previousMember = null;

            while (Reader.NodeType != Mono.System.Xml.XmlNodeType.EndElement && (ind < maxInd - 1))
            {
                if (Reader.NodeType == Mono.System.Xml.XmlNodeType.Element)
                {
                    XmlTypeMapElementInfo info;

                    if (readBySoapOrder)
                    {
                        info = map.GetElement(Reader.LocalName, Reader.NamespaceURI, ind);
                    }
                    else if (hasAnyReturnMember)
                    {
                        info = (XmlTypeMapElementInfo)((XmlTypeMapMemberElement)map.ReturnMember).ElementInfo[0];
                        hasAnyReturnMember = false;
                    }
                    else
                    {
                        if (map.IsOrderDependentMap)
                        {
                            info = map.GetElement(Reader.LocalName, Reader.NamespaceURI, ind);
                        }
                        else
                        {
                            info = map.GetElement(Reader.LocalName, Reader.NamespaceURI);
                        }
                    }

                    if (info != null && !readFlag[info.Member.Index])
                    {
                        if (info.Member != previousMember)
                        {
                            ind = info.ExplicitOrder + 1;
                            // If the member is a flat list don't increase the index, since the next element may
                            // be another item of the list. This is a fix for Xamarin bug #9193.
                            if (info.Member is XmlTypeMapMemberFlatList)
                            {
                                ind--;
                            }
                            previousMember = info.Member;
                        }

                        if (info.Member.GetType() == typeof(XmlTypeMapMemberList))
                        {
                            if (_format == SerializationFormat.Encoded && info.MultiReferenceType)
                            {
                                object list = ReadReferencingElement(out fixup.Ids[info.Member.Index]);
                                if (fixup.Ids[info.Member.Index] == null)                                       // Already read
                                {
                                    if (IsReadOnly(info.Member, info.TypeData, ob, isValueList))
                                    {
                                        throw CreateReadOnlyCollectionException(info.TypeData.FullTypeName);
                                    }
                                    else
                                    {
                                        SetMemberValue(info.Member, ob, list, isValueList);
                                    }
                                }
                                else if (!info.MappedType.TypeData.Type.IsArray)
                                {
                                    if (IsReadOnly(info.Member, info.TypeData, ob, isValueList))
                                    {
                                        list = GetMemberValue(info.Member, ob, isValueList);
                                    }
                                    else
                                    {
                                        list = CreateList(info.MappedType.TypeData.Type);
                                        SetMemberValue(info.Member, ob, list, isValueList);
                                    }
                                    AddFixup(new CollectionFixup(list, new XmlSerializationCollectionFixupCallback(FillList), fixup.Ids[info.Member.Index]));
                                    fixup.Ids[info.Member.Index] = null;                                        // The member already has the value, no further fix needed.
                                }
                            }
                            else
                            {
                                if (IsReadOnly(info.Member, info.TypeData, ob, isValueList))
                                {
                                    ReadListElement(info.MappedType, info.IsNullable, GetMemberValue(info.Member, ob, isValueList), false);
                                }
                                else if (info.MappedType.TypeData.Type.IsArray)
                                {
                                    object list = ReadListElement(info.MappedType, info.IsNullable, null, true);
                                    if (list != null || info.IsNullable)
                                    {
                                        SetMemberValue(info.Member, ob, list, isValueList);
                                    }
                                }
                                else
                                {
                                    // If the member already has a list, reuse that list. No need to create a new one.
                                    object list = GetMemberValue(info.Member, ob, isValueList);
                                    if (list == null)
                                    {
                                        list = CreateList(info.MappedType.TypeData.Type);
                                        SetMemberValue(info.Member, ob, list, isValueList);
                                    }
                                    ReadListElement(info.MappedType, info.IsNullable, list, true);
                                }
                            }
                            readFlag[info.Member.Index] = true;
                        }
                        else if (info.Member.GetType() == typeof(XmlTypeMapMemberFlatList))
                        {
                            XmlTypeMapMemberFlatList mem = (XmlTypeMapMemberFlatList)info.Member;
                            AddListValue(mem.TypeData, ref flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]++, ReadObjectElement(info), !IsReadOnly(info.Member, info.TypeData, ob, isValueList));
                            if (mem.ChoiceMember != null)
                            {
                                AddListValue(mem.ChoiceTypeData, ref flatListsChoices [mem.FlatArrayIndex], indexes[mem.FlatArrayIndex] - 1, info.ChoiceValue, true);
                            }
                        }
                        else if (info.Member.GetType() == typeof(XmlTypeMapMemberAnyElement))
                        {
                            XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement)info.Member;
                            if (mem.TypeData.IsListType)
                            {
                                AddListValue(mem.TypeData, ref flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]++, ReadXmlNode(mem.TypeData.ListItemTypeData, false), true);
                            }
                            else
                            {
                                SetMemberValue(mem, ob, ReadXmlNode(mem.TypeData, false), isValueList);
                            }
                        }
                        else if (info.Member.GetType() == typeof(XmlTypeMapMemberElement))
                        {
                            object val;
                            readFlag[info.Member.Index] = true;
                            if (_format == SerializationFormat.Encoded)
                            {
                                if (info.Member.TypeData.SchemaType != SchemaTypes.Primitive)
                                {
                                    val = ReadReferencingElement(out fixup.Ids[info.Member.Index]);
                                }
                                else
                                {
                                    val = ReadReferencingElement(info.Member.TypeData.XmlType, Mono.System.Xml.Schema.XmlSchema.Namespace, out fixup.Ids[info.Member.Index]);
                                }

                                if (info.MultiReferenceType)
                                {
                                    if (fixup.Ids[info.Member.Index] == null)                                           // already read
                                    {
                                        SetMemberValue(info.Member, ob, val, isValueList);
                                    }
                                }
                                else if (val != null)
                                {
                                    SetMemberValue(info.Member, ob, val, isValueList);
                                }
                            }
                            else
                            {
                                SetMemberValue(info.Member, ob, ReadObjectElement(info), isValueList);
                                if (info.ChoiceValue != null)
                                {
                                    XmlTypeMapMemberElement imem = (XmlTypeMapMemberElement)info.Member;
                                    imem.SetChoice(ob, info.ChoiceValue);
                                }
                            }
                        }
                        else
                        {
                            throw new InvalidOperationException("Unknown member type");
                        }
                    }
                    else if (map.DefaultAnyElementMember != null)
                    {
                        XmlTypeMapMemberAnyElement mem = map.DefaultAnyElementMember;
                        if (mem.TypeData.IsListType)
                        {
                            AddListValue(mem.TypeData, ref flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]++, ReadXmlNode(mem.TypeData.ListItemTypeData, false), true);
                        }
                        else
                        {
                            SetMemberValue(mem, ob, ReadXmlNode(mem.TypeData, false), isValueList);
                        }
                    }
                    else
                    {
                        ProcessUnknownElement(ob);
                    }
                }
                else if ((Reader.NodeType == Mono.System.Xml.XmlNodeType.Text || Reader.NodeType == Mono.System.Xml.XmlNodeType.CDATA) && map.XmlTextCollector != null)
                {
                    if (map.XmlTextCollector is XmlTypeMapMemberExpandable)
                    {
                        XmlTypeMapMemberExpandable mem   = (XmlTypeMapMemberExpandable)map.XmlTextCollector;
                        XmlTypeMapMemberFlatList   flatl = mem as XmlTypeMapMemberFlatList;
                        TypeData itype = (flatl == null) ? mem.TypeData.ListItemTypeData : flatl.ListMap.FindTextElement().TypeData;

                        object val = (itype.Type == typeof(string)) ? (object)Reader.ReadString() : (object)ReadXmlNode(itype, false);
                        AddListValue(mem.TypeData, ref flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]++, val, true);
                    }
                    else
                    {
                        XmlTypeMapMemberElement mem  = (XmlTypeMapMemberElement)map.XmlTextCollector;
                        XmlTypeMapElementInfo   info = (XmlTypeMapElementInfo)mem.ElementInfo [0];
                        if (info.TypeData.Type == typeof(string))
                        {
                            SetMemberValue(mem, ob, ReadString((string)GetMemberValue(mem, ob, isValueList)), isValueList);
                        }
                        else
                        {
                            SetMemberValue(mem, ob, GetValueFromXmlString(Reader.ReadString(), info.TypeData, info.MappedType), isValueList);
                        }
                    }
                }
                else
                {
                    UnknownNode(ob);
                }
                Reader.MoveToContent();
            }

            if (flatLists != null)
            {
                foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
                {
                    Object list = flatLists[mem.FlatArrayIndex];
                    if (mem.TypeData.Type.IsArray)
                    {
                        list = ShrinkArray((Array)list, indexes[mem.FlatArrayIndex], mem.TypeData.Type.GetElementType(), true);
                    }
                    if (!IsReadOnly(mem, mem.TypeData, ob, isValueList) && mem.TypeData.Type.IsArray)
                    {
                        SetMemberValue(mem, ob, list, isValueList);
                    }
                }
            }

            if (flatListsChoices != null)
            {
                foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
                {
                    Object list = flatListsChoices[mem.FlatArrayIndex];
                    if (list == null)
                    {
                        continue;
                    }
                    list = ShrinkArray((Array)list, indexes[mem.FlatArrayIndex], mem.ChoiceTypeData.Type.GetElementType(), true);
                    XmlTypeMapMember.SetValue(ob, mem.ChoiceMember, list);
                }
            }
            SetListMembersDefaults(map, ob, isValueList);
        }
Ejemplo n.º 4
0
        public void AddMember(XmlTypeMapMember member)
        {
            // If GlobalIndex has not been set, set it now
            if (member.GlobalIndex == -1)
            {
                member.GlobalIndex = _allMembers.Count;
            }

            _allMembers.Add(member);

            if (!(member.DefaultValue is DBNull) && member.DefaultValue != null)
            {
                if (_membersWithDefault == null)
                {
                    _membersWithDefault = new ArrayList();
                }
                _membersWithDefault.Add(member);
            }

            if (member.IsReturnValue)
            {
                _returnMember = member;
            }

            if (member is XmlTypeMapMemberAttribute)
            {
                XmlTypeMapMemberAttribute atm = (XmlTypeMapMemberAttribute)member;
                if (_attributeMembers == null)
                {
                    _attributeMembers = new Hashtable();
                }
                string key = BuildKey(atm.AttributeName, atm.Namespace, -1);
                if (_attributeMembers.ContainsKey(key))
                {
                    throw new InvalidOperationException("The XML attribute named '" + atm.AttributeName + "' from namespace '" + atm.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the attribute.");
                }
                member.Index = _attributeMembers.Count;
                _attributeMembers.Add(key, member);
                return;
            }
            else if (member is XmlTypeMapMemberFlatList)
            {
                RegisterFlatList((XmlTypeMapMemberFlatList)member);
            }
            else if (member is XmlTypeMapMemberAnyElement)
            {
                XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement)member;
                if (mem.IsDefaultAny)
                {
                    _defaultAnyElement = mem;
                }
                if (mem.TypeData.IsListType)
                {
                    RegisterFlatList(mem);
                }
            }
            else if (member is XmlTypeMapMemberAnyAttribute)
            {
                _defaultAnyAttribute = (XmlTypeMapMemberAnyAttribute)member;
                return;
            }
            else if (member is XmlTypeMapMemberNamespaces)
            {
                _namespaceDeclarations = (XmlTypeMapMemberNamespaces)member;
                return;
            }

            if (member is XmlTypeMapMemberElement && ((XmlTypeMapMemberElement)member).IsXmlTextCollector)
            {
                if (_xmlTextCollector != null)
                {
                    throw new InvalidOperationException("XmlTextAttribute can only be applied once in a class");
                }
                _xmlTextCollector = member;
            }

            if (_elementMembers == null)
            {
                _elementMembers = new ArrayList();
                _elements       = new Hashtable();
            }

            member.Index = _elementMembers.Count;
            _elementMembers.Add(member);

            ICollection elemsInfo = ((XmlTypeMapMemberElement)member).ElementInfo;

            foreach (XmlTypeMapElementInfo elem in elemsInfo)
            {
                string key = BuildKey(elem.ElementName, elem.Namespace, elem.ExplicitOrder);
                if (_elements.ContainsKey(key))
                {
                    throw new InvalidOperationException("The XML element named '" + elem.ElementName + "' from namespace '" + elem.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.");
                }
                _elements.Add(key, elem);
            }

            if (member.TypeData.IsListType && member.TypeData.Type != null && !member.TypeData.Type.IsArray)
            {
                if (_listMembers == null)
                {
                    _listMembers = new ArrayList();
                }
                _listMembers.Add(member);
            }
        }