using Use = System.Xml.Schema.XmlSchemaUse;
using SOMList = System.Xml.Schema.XmlSchemaObjectCollection;
using SOMObject = System.Xml.Schema.XmlSchemaObject;
+using Import = System.Xml.Schema.XmlSchemaImport;
using Element = System.Xml.Schema.XmlSchemaElement;
using Attr = System.Xml.Schema.XmlSchemaAttribute;
using AttrGroup = System.Xml.Schema.XmlSchemaAttributeGroup;
namespace System.Xml.Schema
{
- [MonoTODO ("merge primitive types; infer gYearMonth too; in some cases sequence should contain element whose minOccurs=0 (no obvious rules right now); reject some non-supported schema components")]
- public class XmlSchemaInference
+ [MonoTODO]
+ // FIXME:
+ // - merge primitive types
+ // - infer gYearMonth too
+ // - in some cases sequence should contain element whose minOccurs=0
+ // (no obvious rules right now)
+ // - reject some non-supported schema components
+ public sealed class XmlSchemaInference
{
public enum InferenceOption {
Restricted,
}
public InferenceOption TypeInference {
- get { return TypeInference; }
+ get { return typeInference; }
set { typeInference = value; }
}
{
public static XmlSchemaSet Process (XmlReader xmlReader,
XmlSchemaSet schemas,
- bool laxOccurence,
+ bool laxOccurrence,
bool laxTypeInference)
{
XsdInference impl = new XsdInference (xmlReader,
- schemas, laxOccurence, laxTypeInference);
+ schemas, laxOccurrence, laxTypeInference);
impl.Run ();
return impl.schemas;
}
- public const string NamespaceXml = "http://www.w3.org/XML/1998/namespace";
+ public const string NamespaceXml =
+ "http://www.w3.org/XML/1998/namespace";
- public const string NamespaceXmlns = "http://www.w3.org/2000/xmlns/";
+ public const string NamespaceXmlns =
+ "http://www.w3.org/2000/xmlns/";
- public const string XdtNamespace = "http://www.w3.org/2003/11/xpath-datatypes";
+ public const string XdtNamespace =
+ "http://www.w3.org/2003/11/xpath-datatypes";
- static readonly QName QNameString = new QName ("string",
- XmlSchema.Namespace);
+ static readonly QName QNameString = new QName (
+ "string", XmlSchema.Namespace);
- static readonly QName QNameBoolean = new QName ("boolean",
- XmlSchema.Namespace);
+ static readonly QName QNameBoolean = new QName (
+ "boolean", XmlSchema.Namespace);
- static readonly QName QNameAnyType = new QName ("anyType",
- XmlSchema.Namespace);
+ static readonly QName QNameAnyType = new QName (
+ "anyType", XmlSchema.Namespace);
+
+ static readonly QName QNameByte = new QName (
+ "byte", XmlSchema.Namespace);
+
+ static readonly QName QNameUByte = new QName (
+ "unsignedByte", XmlSchema.Namespace);
+
+ static readonly QName QNameShort = new QName (
+ "short", XmlSchema.Namespace);
+
+ static readonly QName QNameUShort = new QName (
+ "unsignedShort", XmlSchema.Namespace);
+
+ static readonly QName QNameInt = new QName (
+ "int", XmlSchema.Namespace);
+
+ static readonly QName QNameUInt = new QName (
+ "unsignedInt", XmlSchema.Namespace);
+
+ static readonly QName QNameLong = new QName (
+ "long", XmlSchema.Namespace);
+
+ static readonly QName QNameULong = new QName (
+ "unsignedLong", XmlSchema.Namespace);
+
+ static readonly QName QNameDecimal = new QName (
+ "decimal", XmlSchema.Namespace);
+
+ static readonly QName QNameUDecimal = new QName (
+ "unsignedDecimal", XmlSchema.Namespace);
+
+ static readonly QName QNameDouble = new QName (
+ "double", XmlSchema.Namespace);
+
+ static readonly QName QNameFloat = new QName (
+ "float", XmlSchema.Namespace);
+
+ static readonly QName QNameDateTime = new QName (
+ "dateTime", XmlSchema.Namespace);
+
+ static readonly QName QNameDuration = new QName (
+ "duration", XmlSchema.Namespace);
XmlReader source;
XmlSchemaSet schemas;
- bool laxOccurence;
+ bool laxOccurrence;
bool laxTypeInference;
Hashtable newElements = new Hashtable ();
private XsdInference (XmlReader xmlReader,
XmlSchemaSet schemas,
- bool laxOccurence,
+ bool laxOccurrence,
bool laxTypeInference)
{
this.source = xmlReader;
this.schemas = schemas;
- this.laxOccurence = laxOccurence;
+ this.laxOccurrence = laxOccurrence;
this.laxTypeInference = laxTypeInference;
}
// move to top-level element
source.MoveToContent ();
- int depth = source.Depth;
if (source.NodeType != XmlNodeType.Element)
throw new ArgumentException ("Argument XmlReader content is expected to be an element.");
}
else
InferElement (el, qname.Namespace, false);
+
+ // FIXME: compile again.
+// foreach (XmlSchema schema in schemas.Schemas ())
+// schemas.Reprocess (schema);
+ }
+
+ private void AddImport (string current, string import)
+ {
+ foreach (XmlSchema schema in schemas.Schemas (current)) {
+ bool exists = false;
+ foreach (XmlSchemaExternal e in schema.Includes) {
+ Import imp = e as Import;
+ if (imp != null &&
+ imp.Namespace == import)
+ exists = true;
+ }
+ if (exists)
+ continue;
+ Import newimp = new Import ();
+ newimp.Namespace = import;
+ schema.Includes.Add (newimp);
+ }
}
private void IncludeXmlAttributes ()
Attr attr = table [attrName] as Attr;
if (attr == null) {
attList.Add (InferNewAttribute (
- attrName, isNew));
+ attrName, isNew, ns));
} else {
table.Remove (attrName);
if (attr.RefName != null &&
}
private XmlSchemaAttribute InferNewAttribute (
- QName attrName, bool isNewTypeDefinition)
+ QName attrName, bool isNewTypeDefinition, string ns)
{
Attr attr = null;
bool mergedRequired = false;
}
attr = new Attr ();
attr.RefName = attrName;
+ AddImport (ns, attrName.Namespace);
} else {
// local attribute
attr = new Attr ();
attr.SchemaTypeName =
InferSimpleType (source.Value);
}
- if (!laxOccurence &&
+ if (!laxOccurrence &&
(isNewTypeDefinition || mergedRequired))
attr.Use = Use.Required;
else
typeName);
if (st == null) // non-primitive type => see above.
return QNameString;
- try {
- st.Datatype.ParseValue (value,
- source.NameTable,
- source as IXmlNamespaceResolver);
- // the string value was value
- return typeName;
- } catch {
- // The types were incompatible.
- // FIXME: find the base common type
- return QNameString;
- }
+ do {
+ try {
+ st.Datatype.ParseValue (value,
+ source.NameTable,
+ source as IXmlNamespaceResolver);
+ return typeName;
+ } catch {
+ st = st.BaseXmlSchemaType as XmlSchemaSimpleType;
+ typeName = st != null ? st.QualifiedName : QName.Empty;
+ }
+ } while (typeName != QName.Empty);
+ return QNameString;
}
private SOMList GetAttributes (ComplexType ct)
Element nel = new Element ();
if (source.NamespaceURI == ns)
nel.Name = source.LocalName;
- else
+ else {
nel.RefName = new QName (source.LocalName,
source.NamespaceURI);
+ AddImport (ns, source.NamespaceURI);
+ }
InferElement (nel, source.NamespaceURI, true);
c.Items.Add (nel);
}
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;
private Choice ToSequenceOfChoice (Sequence s)
{
Choice c = new Choice ();
- if (laxOccurence)
+ if (laxOccurrence)
c.MinOccurs = 0;
c.MaxOccursString = "unbounded";
foreach (Particle p in s.Items)
private Sequence CreateSequence ()
{
Sequence s = new Sequence ();
- if (laxOccurence)
+ if (laxOccurrence)
s.MinOccurs = 0;
return s;
}
return QNameString;
switch (value) {
- // 0 and 1 are not infered as byte unlike MS.XSDInfer
+ // 0 and 1 are not inferred as byte unlike MS.XSDInfer
// case "0":
// case "1":
case "true":
try {
long dec = XmlConvert.ToInt64 (value);
if (byte.MinValue <= dec && dec <= byte.MaxValue)
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.UnsignedByte).QualifiedName;
+ return QNameUByte;
if (sbyte.MinValue <= dec && dec <= sbyte.MaxValue)
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Byte).QualifiedName;
+ return QNameByte;
if (ushort.MinValue <= dec && dec <= ushort.MaxValue)
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.UnsignedShort).QualifiedName;
+ return QNameUShort;
if (short.MinValue <= dec && dec <= short.MaxValue)
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Short).QualifiedName;
+ return QNameShort;
if (uint.MinValue <= dec && dec <= uint.MaxValue)
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.UnsignedInt).QualifiedName;
+ return QNameUInt;
if (int.MinValue <= dec && dec <= int.MaxValue)
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Int).QualifiedName;
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Long).QualifiedName;
+ return QNameInt;
+ return QNameLong;
} catch (Exception) {
}
try {
XmlConvert.ToUInt64 (value);
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.UnsignedLong).QualifiedName;
+ return QNameULong;
} catch (Exception) {
}
try {
XmlConvert.ToDecimal (value);
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Decimal).QualifiedName;
+ return QNameDecimal;
} catch (Exception) {
}
try {
double dbl = XmlConvert.ToDouble (value);
if (float.MinValue <= dbl &&
dbl <= float.MaxValue)
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Float).QualifiedName;
+ return QNameFloat;
else
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Double).QualifiedName;
+ return QNameDouble;
} catch (Exception) {
}
try {
// FIXME: also try DateTimeSerializationMode
// and gYearMonth
XmlConvert.ToDateTime (value);
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.DateTime).QualifiedName;
+ return QNameDateTime;
} catch (Exception) {
}
try {
XmlConvert.ToTimeSpan (value);
- return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Duration).QualifiedName;
+ return QNameDuration;
} catch (Exception) {
}