internal void InferElement()

in src/dotnet-svcutil/lib/src/FrameworkFork/Microsoft.Xml/Xml/schema/Inference/infer.cs [650:996]


        internal void InferElement(XmlSchemaElement xse, bool bCreatingNewType, XmlSchema parentSchema)
        {
            bool bEmptyElement = _xtr.IsEmptyElement;
            int lastUsedSeqItem = -1;

            Hashtable table = new Hashtable();
            XmlSchemaType schemaType = GetEffectiveSchemaType(xse, bCreatingNewType);
            XmlSchemaComplexType ct = schemaType as XmlSchemaComplexType;

            //infer type based on content of the current element
            if (_xtr.MoveToFirstAttribute())
            {
                ProcessAttributes(ref xse, schemaType, bCreatingNewType, parentSchema);
            }
            else
            {
                if (!bCreatingNewType && ct != null)
                {   //if type already exists and can potentially have attributes
                    MakeExistingAttributesOptional(ct, null);
                }
            }
            if (ct == null || ct == XmlSchemaComplexType.AnyType)
            { //It was null or simple type, after processing attributes, this might have been set
                ct = xse.SchemaType as XmlSchemaComplexType;
            }
            //xse's type is set either to complex type if attributes exist or null
            if (bEmptyElement)  //<element attr="3232" />
            {
                if (!bCreatingNewType)
                {
                    if (null != ct)
                    {
                        if (null != ct.Particle)

                        {
                            ct.Particle.MinOccurs = 0;
                        }
                        else if (null != ct.ContentModel)
                        {
                            XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
                            sce.BaseTypeName = ST_string;
                            sce.LineNumber = TF_string;
                        }
                    }
                    else if (!xse.SchemaTypeName.IsEmpty)
                    {
                        xse.LineNumber = TF_string;
                        xse.SchemaTypeName = ST_string;
                    }
                }
                else
                {
                    xse.LineNumber = TF_string;
                    //xse.SchemaTypeName = ST_string; //My change
                }
                return; //We are done processing this element - all attributes are already added
            }
            bool bWhiteSpace = false;
            do
            {
                _xtr.Read();
                if (_xtr.NodeType == XmlNodeType.Whitespace)
                {
                    bWhiteSpace = true;
                }
                if (_xtr.NodeType == XmlNodeType.EntityReference)
                {
                    throw new XmlSchemaInferenceException(ResXml.SchInf_entity, 0, 0);
                }
            } while ((!_xtr.EOF) && (_xtr.NodeType != XmlNodeType.EndElement) && (_xtr.NodeType != XmlNodeType.CDATA) && (_xtr.NodeType != XmlNodeType.Element) && (_xtr.NodeType != XmlNodeType.Text));

            if (_xtr.NodeType == XmlNodeType.EndElement)
            {
                if (bWhiteSpace)
                {
                    if (ct != null)
                    {
                        if (null != ct.ContentModel)
                        {
                            XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
                            sce.BaseTypeName = ST_string;
                            sce.LineNumber = TF_string;
                        }
                        else if (bCreatingNewType)
                        {
                            //attributes exist, but both Particle and ContentModel == null - this must be complex type with simpleContent extension
                            XmlSchemaSimpleContent sc = new XmlSchemaSimpleContent();
                            ct.ContentModel = sc;
                            XmlSchemaSimpleContentExtension sce = new XmlSchemaSimpleContentExtension();
                            sc.Content = sce;

                            MoveAttributes(ct, sce, bCreatingNewType);

                            sce.BaseTypeName = ST_string;
                            sce.LineNumber = TF_string;
                        }
                        else
                            ct.IsMixed = true;
                    }
                    else
                    {
                        xse.SchemaTypeName = ST_string;
                        xse.LineNumber = TF_string;
                    }
                }
                if (bCreatingNewType)
                {
                    xse.LineNumber = TF_string;
                    //xse.SchemaTypeName = ST_string; //my change
                }
                else
                {
                    if (null != ct)
                    {
                        if (null != ct.Particle)
                        {
                            ct.Particle.MinOccurs = 0;
                        }
                        else if (null != ct.ContentModel)
                        {
                            XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
                            sce.BaseTypeName = ST_string;
                            sce.LineNumber = TF_string;
                        }
                    }
                    else if (!xse.SchemaTypeName.IsEmpty)
                    {
                        xse.LineNumber = TF_string;
                        xse.SchemaTypeName = ST_string;
                    }
                }

                return; //<element attr="232"></element>
            }
            int iChildNumber = 0;
            bool bCreatingNewSequence = false;
            while (!_xtr.EOF && (_xtr.NodeType != XmlNodeType.EndElement))
            {
                bool bNextNodeAlreadyRead = false;  //In some cases we have to look ahead one node. If true means that we did look ahead.
                iChildNumber++;
                if ((_xtr.NodeType == XmlNodeType.Text) || (_xtr.NodeType == XmlNodeType.CDATA)) //node can be simple type, complex with simple content or complex with mixed content
                {
                    if (null != ct)
                    {
                        if (null != ct.Particle)
                        {
                            ct.IsMixed = true;
                            if (iChildNumber == 1)
                            {
                                //if this is the only child and other elements do not follow, we must set particle minOccurs="0"
                                do { _xtr.Read(); } while ((!_xtr.EOF) && ((_xtr.NodeType == XmlNodeType.CDATA) || (_xtr.NodeType == XmlNodeType.Text) || (_xtr.NodeType == XmlNodeType.Comment) || (_xtr.NodeType == XmlNodeType.ProcessingInstruction) || (_xtr.NodeType == XmlNodeType.Whitespace) || (_xtr.NodeType == XmlNodeType.SignificantWhitespace) || (_xtr.NodeType == XmlNodeType.XmlDeclaration)));
                                bNextNodeAlreadyRead = true;
                                if (_xtr.NodeType == XmlNodeType.EndElement)
                                    ct.Particle.MinOccurs = decimal.Zero;
                            }
                        }
                        else if (null != ct.ContentModel)
                        {   //complexType with simpleContent
                            XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
                            if ((_xtr.NodeType == XmlNodeType.Text) && (iChildNumber == 1))
                            {
                                int SimpleType = -1;
                                if (xse.Parent == null)
                                {
                                    SimpleType = sce.LineNumber; // we use LineNumber to represent valid type flags
                                }
                                else
                                {
                                    SimpleType = GetSchemaType(sce.BaseTypeName);
                                    xse.Parent = null;
                                }
                                sce.BaseTypeName = RefineSimpleType(_xtr.Value, ref SimpleType);
                                sce.LineNumber = SimpleType; // we use LineNumber to represent valid type flags
                            }
                            else
                            {
                                sce.BaseTypeName = ST_string;
                                sce.LineNumber = TF_string;
                            }
                        }
                        else
                        {
                            //attributes exist, but both Particle and ContentModel == null - this must be complex type with simpleContent extension
                            XmlSchemaSimpleContent sc = new XmlSchemaSimpleContent();
                            ct.ContentModel = sc;
                            XmlSchemaSimpleContentExtension sce = new XmlSchemaSimpleContentExtension();
                            sc.Content = sce;

                            MoveAttributes(ct, sce, bCreatingNewType);

                            if (_xtr.NodeType == XmlNodeType.Text)
                            {
                                int TypeFlags;
                                if (!bCreatingNewType)
                                    //previously this was empty element
                                    TypeFlags = TF_string;
                                else
                                    TypeFlags = -1;
                                sce.BaseTypeName = RefineSimpleType(_xtr.Value, ref TypeFlags);
                                sce.LineNumber = TypeFlags; // we use LineNumber to store flags of valid types
                            }
                            else
                            {
                                sce.BaseTypeName = ST_string;
                                sce.LineNumber = TF_string;
                            }
                        }
                    }
                    else
                    {   //node is currently empty or with SimpleType
                        //node will become simple type
                        if (iChildNumber > 1)
                        {
                            //more than one consecutive text nodes probably with PI in between
                            xse.SchemaTypeName = ST_string;
                            xse.LineNumber = TF_string;// we use LineNumber to store flags of valid types
                        }
                        else
                        {
                            int TypeFlags = -1;
                            if (bCreatingNewType)
                                if (_xtr.NodeType == XmlNodeType.Text)
                                {
                                    xse.SchemaTypeName = RefineSimpleType(_xtr.Value, ref TypeFlags);
                                    xse.LineNumber = TypeFlags; // we use LineNumber to store flags of valid types
                                }
                                else
                                {
                                    xse.SchemaTypeName = ST_string;
                                    xse.LineNumber = TF_string;// we use LineNumber to store flags of valid types
                                }
                            else if (_xtr.NodeType == XmlNodeType.Text)
                            {
                                if (xse.Parent == null)
                                {
                                    TypeFlags = xse.LineNumber;
                                }
                                else
                                {
                                    TypeFlags = GetSchemaType(xse.SchemaTypeName);
                                    if (TypeFlags == -1 && xse.LineNumber == TF_string)
                                    { //Since schemaTypeName is not set for empty elements (<e></e>)
                                        TypeFlags = TF_string;
                                    }
                                    xse.Parent = null;
                                }
                                xse.SchemaTypeName = RefineSimpleType(_xtr.Value, ref TypeFlags);    //simple type
                                xse.LineNumber = TypeFlags; // we use LineNumber to store flags of valid types
                            }
                            else
                            {
                                xse.SchemaTypeName = ST_string;
                                xse.LineNumber = TF_string;// we use LineNumber to store flags of valid types
                            }
                        }
                    }
                }
                else if (_xtr.NodeType == XmlNodeType.Element)
                {
                    XmlQualifiedName qname = new XmlQualifiedName(_xtr.LocalName, _xtr.NamespaceURI);
                    bool Maxoccursflag = false;
                    if (table.Contains(qname))
                    {
                        Maxoccursflag = true;
                    }
                    else
                    {
                        table.Add(qname, null);
                    }
                    if (ct == null)
                    { //untill now the element was empty or SimpleType - it now becomes complex type
                        ct = new XmlSchemaComplexType();
                        xse.SchemaType = ct;
                        if (!xse.SchemaTypeName.IsEmpty) //BUGBUG, This assumption is wrong 
                        {
                            ct.IsMixed = true;
                            xse.SchemaTypeName = XmlQualifiedName.Empty;
                        }
                    }
                    if (ct.ContentModel != null)
                    {   //type was previously identified as simple content extension - we need to convert it to sequence
                        XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
                        MoveAttributes(sce, ct);
                        ct.ContentModel = null;
                        ct.IsMixed = true;
                        if (ct.Particle != null)
                            throw new XmlSchemaInferenceException(ResXml.SchInf_particle, 0, 0);
                        ct.Particle = new XmlSchemaSequence();
                        bCreatingNewSequence = true;
                        XmlSchemaElement subelement = AddElement(_xtr.LocalName, _xtr.Prefix, _xtr.NamespaceURI, parentSchema, ((XmlSchemaSequence)ct.Particle).Items, -1);
                        lastUsedSeqItem = 0;
                        if (!bCreatingNewType)
                            ct.Particle.MinOccurs = 0;    //previously this was simple type so subelements did not exist
                    }
                    else if (ct.Particle == null)
                    {
                        ct.Particle = new XmlSchemaSequence();
                        bCreatingNewSequence = true;
                        XmlSchemaElement subelement = AddElement(_xtr.LocalName, _xtr.Prefix, _xtr.NamespaceURI, parentSchema, ((XmlSchemaSequence)ct.Particle).Items, -1);
                        if (!bCreatingNewType)
                        {
                            ((XmlSchemaSequence)ct.Particle).MinOccurs = decimal.Zero;
                            //  subelement.MinOccurs = decimal.Zero;
                        }

                        lastUsedSeqItem = 0;
                    }
                    else
                    {
                        bool bParticleChanged = false;
                        XmlSchemaElement subelement = FindMatchingElement(bCreatingNewType || bCreatingNewSequence, _xtr, ct, ref lastUsedSeqItem, ref bParticleChanged, parentSchema, Maxoccursflag);
                    }
                }
                else if (_xtr.NodeType == XmlNodeType.Text)
                {
                    if (ct == null)
                        throw new XmlSchemaInferenceException(ResXml.SchInf_ct, 0, 0);
                    ct.IsMixed = true;
                }
                do
                {
                    if (_xtr.NodeType == XmlNodeType.EntityReference)
                    {
                        throw new XmlSchemaInferenceException(ResXml.SchInf_entity, 0, 0);
                    }
                    if (!bNextNodeAlreadyRead)
                    {
                        _xtr.Read();
                    }
                    else
                    {
                        bNextNodeAlreadyRead = false;
                    }
                } while ((!_xtr.EOF) && (_xtr.NodeType != XmlNodeType.EndElement) && (_xtr.NodeType != XmlNodeType.CDATA) && (_xtr.NodeType != XmlNodeType.Element) && (_xtr.NodeType != XmlNodeType.Text));
            }
            if (lastUsedSeqItem != -1)
            {
                //Verify if all elements in a sequence exist, if not set MinOccurs=0
                while (++lastUsedSeqItem < ((XmlSchemaSequence)ct.Particle).Items.Count)
                {
                    if (((XmlSchemaSequence)ct.Particle).Items[lastUsedSeqItem].GetType() != typeof(XmlSchemaElement))
                        throw new XmlSchemaInferenceException(ResXml.SchInf_seq, 0, 0);
                    XmlSchemaElement subElement = (XmlSchemaElement)((XmlSchemaSequence)ct.Particle).Items[lastUsedSeqItem];
                    subElement.MinOccurs = 0;
                }
            }
        }