5 // Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
7 // (C)2003 Atsushi Enomoto
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;
33 using System.Collections.Generic;
34 using System.Collections.Specialized;
35 using System.ComponentModel;
37 using System.Security.Policy;
38 using System.Xml.Schema;
39 using System.Xml.XPath;
41 namespace System.Xml.Schema
44 public class XmlSchemaSet
46 internal sealed class XmlSchemaSet
49 XmlNameTable nameTable;
50 XmlResolver xmlResolver = new XmlUrlResolver ();
53 XmlSchemaObjectTable attributes;
54 XmlSchemaObjectTable elements;
55 XmlSchemaObjectTable types;
57 XmlSchemaCompilationSettings settings =
58 new XmlSchemaCompilationSettings ();
62 internal Guid CompilationId { get; private set; }
64 public XmlSchemaSet ()
65 : this (new NameTable ())
69 public XmlSchemaSet (XmlNameTable nameTable)
71 if (nameTable == null)
72 throw new ArgumentNullException ("nameTable");
74 this.nameTable = nameTable;
75 schemas = new ArrayList ();
76 CompilationId = Guid.NewGuid ();
79 public event ValidationEventHandler ValidationEventHandler;
82 get { return schemas.Count; }
85 public XmlSchemaObjectTable GlobalAttributes {
87 if (attributes == null)
88 attributes = new XmlSchemaObjectTable ();
93 public XmlSchemaObjectTable GlobalElements {
96 elements = new XmlSchemaObjectTable ();
101 public XmlSchemaObjectTable GlobalTypes {
104 types = new XmlSchemaObjectTable ();
109 public bool IsCompiled {
110 get { return isCompiled; }
113 public XmlNameTable NameTable {
114 get { return nameTable; }
117 public XmlSchemaCompilationSettings CompilationSettings {
118 get { return settings; }
119 set { settings = value; }
122 public XmlResolver XmlResolver {
123 set { xmlResolver = value; }
125 internal get { return xmlResolver; }
127 get { return xmlResolver; }
131 public XmlSchema Add (string targetNamespace, string schemaUri)
133 var uri = xmlResolver.ResolveUri (null, schemaUri);
134 using (var stream = (Stream) xmlResolver.GetEntity (uri, null, typeof (Stream)))
135 using (var r = XmlReader.Create (stream, new XmlReaderSettings () { XmlResolver = xmlResolver, NameTable = nameTable}))
136 return Add (targetNamespace, r);
139 public XmlSchema Add (string targetNamespace, XmlReader schemaDocument)
141 XmlSchema schema = XmlSchema.Read (schemaDocument, ValidationEventHandler);
142 if (schema.TargetNamespace == null)
143 schema.TargetNamespace = targetNamespace == String.Empty ? null : targetNamespace; // this weirdness is due to bug #571660.
144 else if (targetNamespace != null && schema.TargetNamespace != targetNamespace)
145 throw new XmlSchemaException ("The actual targetNamespace in the schema does not match the parameter.");
151 // FIXME: Check the exact behavior when namespaces are in conflict (but it would be preferable to wait for 2.0 RTM)
152 public void Add (XmlSchemaSet schemas)
154 ArrayList al = new ArrayList ();
155 foreach (XmlSchema schema in schemas.schemas) {
156 if (!this.schemas.Contains (schema))
159 foreach (XmlSchema schema in al)
163 public XmlSchema Add (XmlSchema schema)
165 schemas.Add (schema);
170 // FIXME: It should be the actual compilation engine.
171 public void Compile ()
173 ClearGlobalComponents ();
174 ArrayList al = new ArrayList ();
175 al.AddRange (schemas);
177 var handledUris = new List<CompiledSchemaMemo> ();
178 foreach (XmlSchema schema in al)
179 if (!schema.IsCompiled)
180 schema.CompileSubset (ValidationEventHandler, this, xmlResolver, handledUris);
182 // Process substitutionGroup first, as this process
183 // involves both substituted and substituting elements
184 // and hence it needs to be done before actual
185 // validation (by current design of conformance checker).
186 foreach (XmlSchema schema in al)
187 foreach (XmlSchemaElement elem in schema.Elements.Values)
188 elem.FillSubstitutionElementInfo ();
191 foreach (XmlSchema schema in al)
192 schema.Validate (ValidationEventHandler);
194 foreach (XmlSchema schema in al)
195 AddGlobalComponents (schema);
200 private void ClearGlobalComponents ()
202 GlobalElements.Clear ();
203 GlobalAttributes.Clear ();
204 GlobalTypes.Clear ();
205 global_attribute_groups.Clear ();
206 global_groups.Clear ();
207 global_notations.Clear ();
209 global_identity_constraints.Clear ();
212 XmlSchemaObjectTable global_attribute_groups = new XmlSchemaObjectTable ();
213 XmlSchemaObjectTable global_groups = new XmlSchemaObjectTable ();
214 XmlSchemaObjectTable global_notations = new XmlSchemaObjectTable ();
215 XmlSchemaObjectTable global_identity_constraints = new XmlSchemaObjectTable ();
216 Hashtable global_ids = new Hashtable ();
218 private void AddGlobalComponents (XmlSchema schema)
220 foreach (XmlSchemaElement el in schema.Elements.Values)
221 GlobalElements.Add (el.QualifiedName, el);
222 foreach (XmlSchemaAttribute a in schema.Attributes.Values)
223 GlobalAttributes.Add (a.QualifiedName, a);
224 foreach (XmlSchemaType t in schema.SchemaTypes.Values)
225 GlobalTypes.Add (t.QualifiedName, t);
226 foreach (XmlSchemaAttributeGroup g in schema.AttributeGroups.Values)
227 global_attribute_groups.Add (g.QualifiedName, g);
228 foreach (XmlSchemaGroup g in schema.Groups.Values)
229 global_groups.Add (g.QualifiedName, g);
230 foreach (DictionaryEntry pair in schema.IDCollection)
231 global_ids.Add (pair.Key, pair.Value);
232 foreach (XmlSchemaIdentityConstraint ic in schema.NamedIdentities.Values)
233 global_identity_constraints.Add (ic.QualifiedName, ic);
236 public bool Contains (string targetNamespace)
238 targetNamespace = GetSafeNs (targetNamespace);
239 foreach (XmlSchema schema in schemas)
240 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
245 public bool Contains (XmlSchema schema)
247 foreach (XmlSchema s in schemas)
253 public void CopyTo (XmlSchema [] schemas, int index)
255 this.schemas.CopyTo (schemas, index);
258 internal void CopyTo (Array array, int index)
260 schemas.CopyTo (array, index);
263 string GetSafeNs (string ns)
265 return ns == null ? "" : ns;
269 // FIXME: Check exact behavior
270 public XmlSchema Remove (XmlSchema schema)
273 throw new ArgumentNullException ("schema");
274 ArrayList al = new ArrayList ();
275 al.AddRange (schemas);
276 if (!al.Contains (schema))
278 // FIXME: I have no idea why Remove() might throw
279 // XmlSchemaException, except for the case it compiles.
280 if (!schema.IsCompiled)
281 schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
282 schemas.Remove (schema);
290 ClearGlobalComponents ();
293 public bool RemoveRecursive (XmlSchema schemaToRemove)
295 if (schemaToRemove == null)
296 throw new ArgumentNullException ("schema");
297 ArrayList al = new ArrayList ();
298 al.AddRange (schemas);
299 if (!al.Contains (schemaToRemove))
301 al.Remove (schemaToRemove);
302 schemas.Remove (schemaToRemove);
307 ClearGlobalComponents ();
308 foreach (XmlSchema s in al) {
310 AddGlobalComponents (schemaToRemove);
315 public XmlSchema Reprocess (XmlSchema schema)
318 throw new ArgumentNullException ("schema");
319 ArrayList al = new ArrayList ();
320 al.AddRange (schemas);
321 if (!al.Contains (schema))
322 throw new ArgumentException ("Target schema is not contained in the schema set.");
323 ClearGlobalComponents ();
324 foreach (XmlSchema s in al) {
326 schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
328 AddGlobalComponents (schema);
330 return schema.IsCompiled ? schema : null;
333 public ICollection Schemas ()
338 public ICollection Schemas (string targetNamespace)
340 targetNamespace = GetSafeNs (targetNamespace);
341 ArrayList al = new ArrayList ();
342 foreach (XmlSchema schema in schemas)
343 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
348 internal bool MissedSubComponents (string targetNamespace)
350 foreach (XmlSchema s in Schemas (targetNamespace))
351 if (s.missedSubComponents)