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 XmlTextReader r = null;
135 r = new XmlTextReader (schemaUri, nameTable);
136 return Add (targetNamespace, r);
143 public XmlSchema Add (string targetNamespace, XmlReader schemaDocument)
145 XmlSchema schema = XmlSchema.Read (schemaDocument, ValidationEventHandler);
146 if (schema.TargetNamespace == null)
147 schema.TargetNamespace = targetNamespace == String.Empty ? null : targetNamespace; // this weirdness is due to bug #571660.
148 else if (targetNamespace != null && schema.TargetNamespace != targetNamespace)
149 throw new XmlSchemaException ("The actual targetNamespace in the schema does not match the parameter.");
155 // FIXME: Check the exact behavior when namespaces are in conflict (but it would be preferable to wait for 2.0 RTM)
156 public void Add (XmlSchemaSet schemas)
158 ArrayList al = new ArrayList ();
159 foreach (XmlSchema schema in schemas.schemas) {
160 if (!this.schemas.Contains (schema))
163 foreach (XmlSchema schema in al)
167 public XmlSchema Add (XmlSchema schema)
169 schemas.Add (schema);
174 // FIXME: It should be the actual compilation engine.
175 public void Compile ()
177 ClearGlobalComponents ();
178 ArrayList al = new ArrayList ();
179 al.AddRange (schemas);
181 var handledUris = new List<CompiledSchemaMemo> ();
182 foreach (XmlSchema schema in al)
183 if (!schema.IsCompiled)
184 schema.CompileSubset (ValidationEventHandler, this, xmlResolver, handledUris);
186 // Process substitutionGroup first, as this process
187 // involves both substituted and substituting elements
188 // and hence it needs to be done before actual
189 // validation (by current design of conformance checker).
190 foreach (XmlSchema schema in al)
191 foreach (XmlSchemaElement elem in schema.Elements.Values)
192 elem.FillSubstitutionElementInfo ();
195 foreach (XmlSchema schema in al)
196 schema.Validate (ValidationEventHandler);
198 foreach (XmlSchema schema in al)
199 AddGlobalComponents (schema);
204 private void ClearGlobalComponents ()
206 GlobalElements.Clear ();
207 GlobalAttributes.Clear ();
208 GlobalTypes.Clear ();
209 global_attribute_groups.Clear ();
210 global_groups.Clear ();
211 global_notations.Clear ();
213 global_identity_constraints.Clear ();
216 XmlSchemaObjectTable global_attribute_groups = new XmlSchemaObjectTable ();
217 XmlSchemaObjectTable global_groups = new XmlSchemaObjectTable ();
218 XmlSchemaObjectTable global_notations = new XmlSchemaObjectTable ();
219 XmlSchemaObjectTable global_identity_constraints = new XmlSchemaObjectTable ();
220 Hashtable global_ids = new Hashtable ();
222 private void AddGlobalComponents (XmlSchema schema)
224 foreach (XmlSchemaElement el in schema.Elements.Values)
225 GlobalElements.Add (el.QualifiedName, el);
226 foreach (XmlSchemaAttribute a in schema.Attributes.Values)
227 GlobalAttributes.Add (a.QualifiedName, a);
228 foreach (XmlSchemaType t in schema.SchemaTypes.Values)
229 GlobalTypes.Add (t.QualifiedName, t);
230 foreach (XmlSchemaAttributeGroup g in schema.AttributeGroups.Values)
231 global_attribute_groups.Add (g.QualifiedName, g);
232 foreach (XmlSchemaGroup g in schema.Groups.Values)
233 global_groups.Add (g.QualifiedName, g);
234 foreach (DictionaryEntry pair in schema.IDCollection)
235 global_ids.Add (pair.Key, pair.Value);
236 foreach (XmlSchemaIdentityConstraint ic in schema.NamedIdentities.Values)
237 global_identity_constraints.Add (ic.QualifiedName, ic);
240 public bool Contains (string targetNamespace)
242 targetNamespace = GetSafeNs (targetNamespace);
243 foreach (XmlSchema schema in schemas)
244 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
249 public bool Contains (XmlSchema schema)
251 foreach (XmlSchema s in schemas)
257 public void CopyTo (XmlSchema [] schemas, int index)
259 this.schemas.CopyTo (schemas, index);
262 internal void CopyTo (Array array, int index)
264 schemas.CopyTo (array, index);
267 string GetSafeNs (string ns)
269 return ns == null ? "" : ns;
273 // FIXME: Check exact behavior
274 public XmlSchema Remove (XmlSchema schema)
277 throw new ArgumentNullException ("schema");
278 ArrayList al = new ArrayList ();
279 al.AddRange (schemas);
280 if (!al.Contains (schema))
282 // FIXME: I have no idea why Remove() might throw
283 // XmlSchemaException, except for the case it compiles.
284 if (!schema.IsCompiled)
285 schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
286 schemas.Remove (schema);
294 ClearGlobalComponents ();
297 public bool RemoveRecursive (XmlSchema schemaToRemove)
299 if (schemaToRemove == null)
300 throw new ArgumentNullException ("schema");
301 ArrayList al = new ArrayList ();
302 al.AddRange (schemas);
303 if (!al.Contains (schemaToRemove))
305 al.Remove (schemaToRemove);
306 schemas.Remove (schemaToRemove);
311 ClearGlobalComponents ();
312 foreach (XmlSchema s in al) {
314 AddGlobalComponents (schemaToRemove);
319 public XmlSchema Reprocess (XmlSchema schema)
322 throw new ArgumentNullException ("schema");
323 ArrayList al = new ArrayList ();
324 al.AddRange (schemas);
325 if (!al.Contains (schema))
326 throw new ArgumentException ("Target schema is not contained in the schema set.");
327 ClearGlobalComponents ();
328 foreach (XmlSchema s in al) {
330 schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
332 AddGlobalComponents (schema);
334 return schema.IsCompiled ? schema : null;
337 public ICollection Schemas ()
342 public ICollection Schemas (string targetNamespace)
344 targetNamespace = GetSafeNs (targetNamespace);
345 ArrayList al = new ArrayList ();
346 foreach (XmlSchema schema in schemas)
347 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
352 internal bool MissedSubComponents (string targetNamespace)
354 foreach (XmlSchema s in Schemas (targetNamespace))
355 if (s.missedSubComponents)