2 // XsdDatatypeProvider.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (c) 2004 Novell Inc.
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
35 using System.Xml.Schema;
37 using XSchema = System.Xml.Schema.XmlSchema;
39 namespace Commons.Xml.Relaxng.XmlSchema
41 public class XsdDatatypeProvider : RelaxngDatatypeProvider
43 static XsdDatatypeProvider instance = new XsdDatatypeProvider ();
44 static Hashtable table;
45 static XsdQNameWrapper qnameType = new XsdQNameWrapper ();
47 private XsdDatatypeProvider ()
52 table = new Hashtable ();
54 // TODO: fill all type names.
55 string [] names = new string [] {
61 "NMTOKEN", "NMTOKENS",
63 "ID", "IDREF", "IDREFS",
64 "ENTITY", "ENTITIES", //"NOTATION",
66 "integer", "long", "int", "short", "byte",
67 "nonPositiveInteger", "negativeInteger",
68 "nonNegativeInteger", "positiveInteger",
69 "unsignedLong", "unsignedInt",
70 "unsignedShort", "unsignedByte",
72 "base64Binary", "hexBinary",
75 "duration", "dateTime", "date", "time",
77 "gYearMonth", "gMonthDay",
78 "gYear", "gMonth", "gDay",
81 StringBuilder sb = new StringBuilder ();
82 sb.Append ("<xs:schema xmlns:xs='" + XSchema.Namespace + "'>");
83 foreach (string name in names)
84 sb.Append ("<xs:element name='" + name + "' type='xs:" + name + "'/>");
85 sb.Append ("</xs:schema>");
86 XSchema schema = XSchema.Read (new XmlTextReader (sb.ToString (), XmlNodeType.Document, null), null);
87 schema.Compile (null);
88 foreach (XmlSchemaElement el in schema.Elements.Values)
89 table.Add (el.Name, new XsdPrimitiveType (el.Name, el.ElementType as XmlSchemaDatatype));
92 public static XsdDatatypeProvider Instance {
93 get { return instance; }
96 public override RelaxngDatatype GetDatatype (string name, string ns, RelaxngParamList parameters)
98 RelaxngDatatype dt = GetPrimitiveType (name, ns);
101 else if (parameters == null || parameters.Count == 0)
104 return new XsdSimpleRestrictionType (dt, parameters);
107 private RelaxngDatatype GetPrimitiveType (string name, string ns)
110 case System.Xml.Schema.XmlSchema.Namespace:
111 case "http://www.w3.org/2001/XMLSchema-datatypes":
118 return table [name] as RelaxngDatatype;
123 public class XsdSimpleRestrictionType : RelaxngDatatype
125 XmlSchemaSimpleType type;
128 public XsdSimpleRestrictionType (RelaxngDatatype primitive, RelaxngParamList parameters)
130 type = new XmlSchemaSimpleType ();
131 XmlSchemaSimpleTypeRestriction r =
132 new XmlSchemaSimpleTypeRestriction ();
134 string ns = primitive.NamespaceURI;
135 // Remap XML Schema datatypes namespace -> XML Schema namespace.
136 if (ns == "http://www.w3.org/2001/XMLSchema-datatypes")
137 ns = XSchema.Namespace;
138 r.BaseTypeName = new XmlQualifiedName (primitive.Name, ns);
139 foreach (RelaxngParam p in parameters) {
140 XmlSchemaFacet f = null;
143 f = new XmlSchemaMaxExclusiveFacet ();
146 f = new XmlSchemaMaxInclusiveFacet ();
149 f = new XmlSchemaMinExclusiveFacet ();
152 f = new XmlSchemaMinInclusiveFacet ();
155 f = new XmlSchemaPatternFacet ();
158 f = new XmlSchemaWhiteSpaceFacet ();
161 f = new XmlSchemaLengthFacet ();
164 f = new XmlSchemaMaxLengthFacet ();
167 f = new XmlSchemaMinLengthFacet ();
169 case "fractionDigits":
170 f = new XmlSchemaFractionDigitsFacet ();
173 f = new XmlSchemaTotalDigitsFacet ();
176 throw new RelaxngException (String.Format ("XML Schema facet {0} is not recognized or not supported.", p.Name));
182 // Now we create XmlSchema to handle simple-type
183 // based validation (since there is no other way,
184 // because of sucky XmlSchemaSimpleType design).
185 schema = new XSchema ();
186 XmlSchemaElement el = new XmlSchemaElement ();
188 el.SchemaType = type;
189 schema.Items.Add (el);
192 public override string Name {
193 get { return type.QualifiedName.Name; }
196 public override string NamespaceURI {
197 get { return type.QualifiedName.Namespace; }
200 internal override bool IsContextDependent {
201 get { return type.Datatype != null && type.Datatype.TokenizedType == XmlTokenizedType.QName; }
204 public override object Parse (string value, XmlReader reader)
206 // Now we create XmlValidatingReader to handle
207 // simple-type based validation (since there is no
208 // other way, because of sucky XmlSchemaSimpleType
210 XmlValidatingReader v = new XmlValidatingReader (
212 String.Concat ("<root>", value, "</root>"),
213 XmlNodeType.Document,
215 v.Schemas.Add (schema);
218 return v.ReadTypedValue ();
220 v.Read (); // </root>
225 public class XsdPrimitiveType : RelaxngDatatype
227 XmlSchemaDatatype dt;
230 public XsdPrimitiveType (string name, XmlSchemaDatatype xstype)
236 internal override bool IsContextDependent {
237 get { return dt.TokenizedType == XmlTokenizedType.QName; }
240 public override string Name {
244 public override string NamespaceURI {
245 get { return "http://www.w3.org/2001/XMLSchema-datatypes"; }
248 public override object Parse (string text, XmlReader reader)
250 return dt.ParseValue (text,
251 reader != null ? reader.NameTable : null,
256 // since QName resolution will fail, it must be implemented differently.
257 public class XsdQNameWrapper : RelaxngDatatype
259 public XsdQNameWrapper ()
263 public override string Name {
264 get { return "QName"; }
267 public override string NamespaceURI {
268 get { return "http://www.w3.org/2001/XMLSchema-datatypes"; }
271 internal override bool IsContextDependent {
275 public override object Parse (string s, XmlReader reader)
277 int colonAt = s.IndexOf (':');
278 string localName = colonAt < 0 ? s : s.Substring (colonAt + 1);
279 // string localName = nameTable.Add (colonAt < 0 ? s : s.Substring (colonAt + 1));
280 return new XmlQualifiedName (localName, reader.LookupNamespace (
281 colonAt < 0 ? "" : s.Substring (0, colonAt - 1)));