private Particle PopulateParticle(ComplexType ct) { if (ct.ContentModel == null) { if (ct.Particle == null) { ct.Particle = CreateSequence(); } return(ct.Particle); } ComplexModel cm = ct.ContentModel as ComplexModel; if (cm != null) { ComplexExt ce = cm.Content as ComplexExt; if (ce != null) { if (ce.Particle == null) { ce.Particle = CreateSequence(); } return(ce.Particle); } ComplexRst cr = cm.Content as ComplexRst; if (cr != null) { if (cr.Particle == null) { cr.Particle = CreateSequence(); } return(cr.Particle); } } throw Error(ct, "Schema inference internal error. The complexType should have been converted to have a complex content."); }
private void MarkAsMixed(ComplexType ct) { ComplexModel cm = ct.ContentModel as ComplexModel; if (cm != null) { cm.IsMixed = true; } else { ct.IsMixed = true; } }
private Sequence PopulateSequence(ComplexType ct) { Particle p = PopulateParticle(ct); Sequence s = p as Sequence; if (s != null) { return(s); } else { throw Error(ct, String.Format("Target complexType contains unacceptable type of particle {0}", p)); } }
private void InferComplexContent(Element el, string ns, bool isNew) { ComplexType ct = ToComplexType(el); ToComplexContentType(ct); int position = 0; bool consumed = false; do { switch (source.NodeType) { case XmlNodeType.Element: Sequence s = PopulateSequence(ct); Choice c = s.Items.Count > 0 ? s.Items [0] as Choice : null; if (c != null) { ProcessLax(c, ns); } else { ProcessSequence(ct, s, ns, ref position, ref consumed, isNew); } source.MoveToContent(); break; case XmlNodeType.Text: case XmlNodeType.CDATA: case XmlNodeType.SignificantWhitespace: MarkAsMixed(ct); source.ReadString(); source.MoveToContent(); break; case XmlNodeType.EndElement: return; // finished case XmlNodeType.None: throw new NotImplementedException("Internal Error: Should not happen."); } } while (true); }
private void InferAsEmptyElement(Element el, string ns, bool isNew) { ComplexType ct = el.SchemaType as ComplexType; if (ct != null) { SimpleModel sm = ct.ContentModel as SimpleModel; if (sm != null) { ToEmptiableSimpleContent(sm, isNew); return; } ComplexModel cm = ct.ContentModel as ComplexModel; if (cm != null) { ToEmptiableComplexContent(cm, isNew); return; } if (ct.Particle != null) { ct.Particle.MinOccurs = 0; } return; } SimpleType st = el.SchemaType as SimpleType; if (st != null) { st = MakeBaseTypeAsEmptiable(st); switch (st.QualifiedName.Namespace) { case XmlSchema.Namespace: case XdtNamespace: el.SchemaTypeName = st.QualifiedName; break; default: el.SchemaType = st; break; } } }
private SOMList GetAttributes(ComplexType ct) { if (ct.ContentModel == null) { return(ct.Attributes); } SimpleModel sc = ct.ContentModel as SimpleModel; if (sc != null) { SimpleExt sce = sc.Content as SimpleExt; if (sce != null) { return(sce.Attributes); } SimpleRst scr = sc.Content as SimpleRst; if (scr != null) { return(scr.Attributes); } else { throw Error(sc, "Invalid simple content model."); } } ComplexModel cc = ct.ContentModel as ComplexModel; if (cc != null) { ComplexExt cce = cc.Content as ComplexExt; if (cce != null) { return(cce.Attributes); } ComplexRst ccr = cc.Content as ComplexRst; if (ccr != null) { return(ccr.Attributes); } else { throw Error(cc, "Invalid simple content model."); } } throw Error(cc, "Invalid complexType. Should not happen."); }
// It makes complexType not to have Simple content model. private void ToComplexContentType(ComplexType type) { SimpleModel sm = type.ContentModel as SimpleModel; if (sm == null) { return; } SOMList atts = GetAttributes(type); foreach (SOMObject o in atts) { type.Attributes.Add(o); } // FIXME: need to copy AnyAttribute. // (though not considered right now) type.ContentModel = null; type.IsMixed = true; }
private void InferTextContent(Element el, bool isNew) { string value = source.ReadString(); if (el.SchemaType == null) { if (el.SchemaTypeName == QName.Empty) { // no type information -> infer type if (isNew) { el.SchemaTypeName = InferSimpleType( value); } else { el.SchemaTypeName = QNameString; } return; } switch (el.SchemaTypeName.Namespace) { case XmlSchema.Namespace: case XdtNamespace: // existing primitive type el.SchemaTypeName = InferMergedType( value, el.SchemaTypeName); break; default: ComplexType ct = schemas.GlobalTypes [ el.SchemaTypeName] as ComplexType; // If it is complex, then just set // mixed='true' (type cannot be set.) // If it is simple, then we cannot // make sure that string value is // valid. So just set as xs:string. if (ct != null) { MarkAsMixed(ct); } else { el.SchemaTypeName = QNameString; } break; } return; } // simpleType SimpleType st = el.SchemaType as SimpleType; if (st != null) { // If simple, then (described above) el.SchemaType = null; el.SchemaTypeName = QNameString; return; } // complexType ComplexType ect = el.SchemaType as ComplexType; SimpleModel sm = ect.ContentModel as SimpleModel; if (sm == null) { // - ComplexContent MarkAsMixed(ect); return; } // - SimpleContent SimpleExt se = sm.Content as SimpleExt; if (se != null) { se.BaseTypeName = InferMergedType(value, se.BaseTypeName); } SimpleRst sr = sm.Content as SimpleRst; if (sr != null) { sr.BaseTypeName = InferMergedType(value, sr.BaseTypeName); sr.BaseType = null; } }
private ComplexType ToComplexType(Element el) { QName name = el.SchemaTypeName; XmlSchemaType type = el.SchemaType; // 1. element type is complex. ComplexType ct = type as ComplexType; if (ct != null) { return(ct); } // 2. reference to global complexType. XmlSchemaType globalType = schemas.GlobalTypes [name] as XmlSchemaType; ct = globalType as ComplexType; if (ct != null) { return(ct); } ct = new ComplexType(); el.SchemaType = ct; el.SchemaTypeName = QName.Empty; // 3. base type name is xs:anyType or no specification. // <xs:complexType /> if (name == QNameAnyType) { return(ct); } else if (type == null && name == QName.Empty) { return(ct); } SimpleModel sc = new SimpleModel(); ct.ContentModel = sc; // 4. type is simpleType // -> extension of existing simple type. SimpleType st = type as SimpleType; if (st != null) { SimpleRst scr = new SimpleRst(); scr.BaseType = st; sc.Content = scr; return(ct); } SimpleExt sce = new SimpleExt(); sc.Content = sce; // 5. type name points to primitive type // -> simple extension of a primitive type st = XmlSchemaType.GetBuiltInSimpleType(name); if (st != null) { sce.BaseTypeName = name; return(ct); } // 6. type name points to global simpleType. st = globalType as SimpleType; if (st != null) { sce.BaseTypeName = name; return(ct); } throw Error(el, "Unexpected schema component that contains simpleTypeName that could not be resolved."); }
private void InferAttributes(Element el, string ns, bool isNew) { // Now this element is going to have complexType. // It currently not, then we have to replace it. ComplexType ct = null; SOMList attList = null; Hashtable table = null; do { switch (source.NamespaceURI) { case NamespaceXml: if (schemas.Schemas( NamespaceXml).Count == 0) { IncludeXmlAttributes(); } break; case XmlSchema.InstanceNamespace: if (source.LocalName == "nil") { el.IsNillable = true; } // all other xsi:* atts are ignored continue; case NamespaceXmlns: continue; } if (ct == null) { ct = ToComplexType(el); attList = GetAttributes(ct); table = CollectAttrTable(attList); } QName attrName = new QName( source.LocalName, source.NamespaceURI); Attr attr = table [attrName] as Attr; if (attr == null) { attList.Add(InferNewAttribute( attrName, isNew, ns)); } else { table.Remove(attrName); if (attr.RefName != null && attr.RefName != QName.Empty) { continue; // just a reference } InferMergedAttribute(attr); } } while (source.MoveToNextAttribute()); // mark all attr definitions that did not appear // as optional. if (table != null) { foreach (Attr attr in table.Values) { attr.Use = Use.Optional; } } }
private void ProcessSequence(ComplexType ct, Sequence s, string ns, ref int position, ref bool consumed, bool isNew) { for (int i = 0; i < position; i++) { Element iel = s.Items [i] as Element; if (ElementMatches(iel, ns)) { // Sequence element type violation // might happen (might not, but we // cannot backtrack here). So switch // to sequence of choice* here. ProcessLax(ToSequenceOfChoice(s), ns); return; } } if (s.Items.Count <= position) { QName name = new QName(source.LocalName, source.NamespaceURI); Element nel = CreateElement(name); if (laxOccurrence) { nel.MinOccurs = 0; } InferElement(nel, ns, true); if (ns == name.Namespace) { s.Items.Add(nel); } else { Element re = new Element(); if (laxOccurrence) { re.MinOccurs = 0; } re.RefName = name; AddImport(ns, name.Namespace); s.Items.Add(re); } consumed = true; return; } Element el = s.Items [position] as Element; if (el == null) { throw Error(s, String.Format("Target complex type content sequence has an unacceptable type of particle {0}", s.Items [position])); } bool matches = ElementMatches(el, ns); if (matches) { if (consumed) { el.MaxOccursString = "unbounded"; } InferElement(el, source.NamespaceURI, false); source.MoveToContent(); switch (source.NodeType) { case XmlNodeType.None: if (source.NodeType == XmlNodeType.Element) { goto case XmlNodeType.Element; } else if (source.NodeType == XmlNodeType.EndElement) { goto case XmlNodeType.EndElement; } break; case XmlNodeType.Element: ProcessSequence(ct, s, ns, ref position, ref consumed, isNew); break; case XmlNodeType.Text: case XmlNodeType.CDATA: case XmlNodeType.SignificantWhitespace: MarkAsMixed(ct); source.ReadString(); goto case XmlNodeType.None; case XmlNodeType.Whitespace: source.ReadString(); goto case XmlNodeType.None; case XmlNodeType.EndElement: return; default: source.Read(); break; } } else { if (consumed) { position++; consumed = false; ProcessSequence(ct, s, ns, ref position, ref consumed, isNew); } else { ProcessLax(ToSequenceOfChoice(s), ns); } } }