Example #1
0
        public XdtoObjectType(XmlSchemaComplexType xmlType, XdtoFactory factory)
        {
            Name         = xmlType.QualifiedName.Name;
            NamespaceUri = xmlType.QualifiedName.Namespace;

            Abstract = xmlType.IsAbstract;
            Mixed    = xmlType.IsMixed;

            var properties = new List <XdtoProperty> ();

            var particle = xmlType.Particle;

            if (xmlType.ContentModel is XmlSchemaComplexContent)
            {
                var complexContent = xmlType.ContentModel as XmlSchemaComplexContent;
                if (complexContent.Content is XmlSchemaComplexContentExtension)
                {
                    var extension = complexContent.Content as XmlSchemaComplexContentExtension;
                    BaseType = factory.Type(Normalize(extension.BaseTypeName, NamespaceUri)) as XdtoObjectType;
                    particle = extension.Particle;
                }
                else
                {
                    throw new NotImplementedException("Недоработочка в XDTO-объекте");
                }
            }

            if (particle is XmlSchemaSequence)
            {
                var sequence = particle as XmlSchemaSequence;

                foreach (var item in sequence.Items)
                {
                    var       element = item as XmlSchemaElement;
                    IXdtoType propertyType;
                    if (!element.SchemaTypeName.IsEmpty)
                    {
                        propertyType = new TypeResolver(factory, element.SchemaTypeName);
                    }
                    else
                    {
                        var type = element.SchemaType;
                        if (type is XmlSchemaSimpleType)
                        {
                            propertyType = new XdtoValueType(type as XmlSchemaSimpleType, factory);
                        }
                        else if (type is XmlSchemaComplexType)
                        {
                            propertyType = new XdtoObjectType(type as XmlSchemaComplexType, factory);
                        }
                        else
                        {
                            propertyType = new XdtoObjectType();
                        }
                    }

                    var minOccurs = element.MinOccurs;
                    var maxOccurs = string.Equals(element.MaxOccursString, "unbounded", StringComparison.Ordinal)
                                                        ? -1
                                                        : element.MaxOccurs
                    ;

                    properties.Add(new XdtoProperty(this, null,
                                                    XmlFormEnum.Element,
                                                    element.QualifiedName.Namespace,
                                                    element.QualifiedName.Name,
                                                    (int)minOccurs, (int)maxOccurs,
                                                    propertyType));
                }
            }
            else if (particle is XmlSchemaChoice)
            {
                var choice = particle as XmlSchemaChoice;
                foreach (var item in choice.Items)
                {
                    var element = item as XmlSchemaElement;
                    // TODO: копипаста
                    IXdtoType propertyType;
                    if (!element.SchemaTypeName.IsEmpty)
                    {
                        propertyType = new TypeResolver(factory, element.SchemaTypeName);
                    }
                    else
                    {
                        var type = element.SchemaType;
                        if (type is XmlSchemaSimpleType)
                        {
                            propertyType = new XdtoValueType(type as XmlSchemaSimpleType, factory);
                        }
                        else if (type is XmlSchemaComplexType)
                        {
                            propertyType = new XdtoObjectType(type as XmlSchemaComplexType, factory);
                        }
                        else
                        {
                            throw new NotImplementedException("Anonymous type...");
                        }
                    }

                    properties.Add(new XdtoProperty(this, null,
                                                    XmlFormEnum.Element,
                                                    element.QualifiedName.Namespace,
                                                    element.QualifiedName.Name,
                                                    0, 1,
                                                    propertyType));
                }
            }
            else
            {
                throw new NotImplementedException("Недоработочка в XDTO-объекте");
            }

            Properties = new XdtoPropertyCollection(properties);
        }
Example #2
0
 public IXdtoType Resolve()
 {
     return(_factory.Type(_xmlType));
 }
Example #3
0
        public IXdtoValue ReadXml(XmlReaderImpl reader, IXdtoType expectedType, XdtoFactory factory)
        {
            // TODO: дублирование кода в трёх ветках

            var result = new XdtoDataObject(this, null, null);

            // TODO: Перевести XML на простые перечисления
            var xmlNodeTypeEnum = XmlNodeTypeEnum.CreateInstance();
            var xmlElementStart = xmlNodeTypeEnum.FromNativeValue(System.Xml.XmlNodeType.Element);
            var xmlText         = xmlNodeTypeEnum.FromNativeValue(System.Xml.XmlNodeType.Text);
            var xmlElementEnd   = xmlNodeTypeEnum.FromNativeValue(System.Xml.XmlNodeType.EndElement);

            while (reader.ReadAttribute())
            {
                if (reader.NamespaceURI.Equals("http://www.w3.org/2000/xmlns/") ||
                    reader.NamespaceURI.Equals(XmlNs.xsi) && reader.LocalName.Equals("type"))
                {
                    continue;
                }
                var propertyName       = reader.LocalName;
                var attributeNamespace = reader.NamespaceURI;
                var attributeProperty  =
                    AllProperties().FirstOrDefault(p => p.Form == XmlFormEnum.Attribute &&
                                                   p.LocalName.Equals(propertyName) &&
                                                   p.NamespaceURI.Equals(attributeNamespace));

                if (attributeProperty == null)
                {
                    if (!Open)
                    {
                        throw new XdtoException($"Ошиба разбора XDTO: Получили неизвестный атрибут {propertyName}");
                    }
                    var type = factory.Type(new XmlDataType("string"));
                    attributeProperty = new XdtoProperty(null, result, XmlFormEnum.Attribute,
                                                         NamespaceUri, propertyName,
                                                         1, -1, type); // TODO: lower / upper для открытого типа
                }

                var attributeValue = attributeProperty.Type.Reader.ReadXml(reader, attributeProperty.Type, factory);
                result.Set(attributeProperty, ValueFactory.Create(attributeValue));
            }

            while (reader.Read())
            {
                if (reader.NodeType.Equals(xmlElementEnd))
                {
                    // TODO: result.Validate()
                    return(result);
                }

                if (reader.NodeType.Equals(xmlText))
                {
                    // надо найти свойство с Form=Text
                    // оно должно быть одно

                    var       textProperty = AllProperties().FirstOrDefault((p) => p.Form == XmlFormEnum.Text);
                    IXdtoType type;
                    IValue    textValue;
                    if (textProperty == null)
                    {
                        if (!Open)
                        {
                            throw new XdtoException($"Ошибка разбора XDTO: Текст {reader.Value} в неположенном месте при разборе типа {this}!");
                        }

                        textProperty = new XdtoProperty(null, result, XmlFormEnum.Text, NamespaceUri, "#text");
                        type         = factory.Type(new XmlDataType("string"));
                        textValue    = ValueFactory.Create(reader.Value);
                    }
                    else
                    {
                        type      = textProperty.Type;
                        textValue = ValueFactory.Create(type.Reader.ReadXml(reader, type, factory));
                    }

                    if (Sequenced)
                    {
                        result.Sequence().Add(textValue.AsString());
                    }
                    else
                    {
                        result.Set(textProperty, textValue);
                    }
                }
                else if (reader.NodeType.Equals(xmlElementStart))
                {
                    var localName = reader.LocalName;
                    var ns        = reader.NamespaceURI;

                    var property = AllProperties().FirstOrDefault((p) => p.LocalName.Equals(localName) &&
                                                                  p.NamespaceURI.Equals(ns) &&
                                                                  p.Form == XmlFormEnum.Element);
                    if (property == null)
                    {
                        if (!Open)
                        {
                            throw new XdtoException($"Ошибка разбора XDTO: Получили неизвестный элемент {localName}");
                        }

                        // TODO: lower / upper для открытого типа
                        property = new XdtoProperty(null, result, XmlFormEnum.Element, ns, localName, 1, 1);
                    }

                    var elementValue = factory.ReadXml(reader, property.Type);

                    // TODO: Разбор anyType
                    if (property.UpperBound != 1)
                    {
                        // TODO: проверка на null - на отсутствие/наличие списка
                        (result.GetList(property) as XdtoList).Add(elementValue);
                    }
                    else
                    {
                        result.Set(property, elementValue);
                    }
                }
            }

            throw new XdtoException("Ошибка разбора XDTO!");
        }