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.Specialized;
34 using System.ComponentModel;
36 using System.Security.Policy;
37 using System.Xml.Schema;
38 using System.Xml.XPath;
40 namespace System.Xml.Schema
43 public class XmlSchemaSet
45 internal sealed class XmlSchemaSet
48 XmlNameTable nameTable;
49 XmlResolver xmlResolver = new XmlUrlResolver ();
52 XmlSchemaObjectTable attributes;
53 XmlSchemaObjectTable elements;
54 XmlSchemaObjectTable types;
55 // XmlSchemaObjectTable attributeGroups;
56 // XmlSchemaObjectTable groups;
57 Hashtable idCollection;
58 XmlSchemaObjectTable namedIdentities;
60 XmlSchemaCompilationSettings settings =
61 new XmlSchemaCompilationSettings ();
65 internal Guid CompilationId;
67 public XmlSchemaSet ()
68 : this (new NameTable ())
72 public XmlSchemaSet (XmlNameTable nameTable)
74 if (nameTable == null)
75 throw new ArgumentNullException ("nameTable");
77 this.nameTable = nameTable;
78 schemas = new ArrayList ();
79 CompilationId = Guid.NewGuid ();
82 public event ValidationEventHandler ValidationEventHandler;
85 get { return schemas.Count; }
88 public XmlSchemaObjectTable GlobalAttributes {
90 if (attributes == null)
91 attributes = new XmlSchemaObjectTable ();
96 public XmlSchemaObjectTable GlobalElements {
99 elements = new XmlSchemaObjectTable ();
104 public XmlSchemaObjectTable GlobalTypes {
107 types = new XmlSchemaObjectTable ();
112 public bool IsCompiled {
113 get { return isCompiled; }
116 public XmlNameTable NameTable {
117 get { return nameTable; }
120 public XmlSchemaCompilationSettings CompilationSettings {
121 get { return settings; }
122 set { settings = value; }
125 public XmlResolver XmlResolver {
126 set { xmlResolver = value; }
128 internal get { return xmlResolver; }
130 get { return xmlResolver; }
134 internal Hashtable IDCollection {
136 if (idCollection == null)
137 idCollection = new Hashtable ();
142 internal XmlSchemaObjectTable NamedIdentities {
144 if (namedIdentities == null)
145 namedIdentities = new XmlSchemaObjectTable();
146 return namedIdentities;
150 public XmlSchema Add (string targetNamespace, string url)
152 XmlTextReader r = null;
154 r = new XmlTextReader (url, nameTable);
155 return Add (targetNamespace, r);
162 public XmlSchema Add (string targetNamespace, XmlReader reader)
164 XmlSchema schema = XmlSchema.Read (reader, ValidationEventHandler);
165 if (schema.TargetNamespace == null)
166 schema.TargetNamespace = targetNamespace;
167 else if (targetNamespace != null && schema.TargetNamespace != targetNamespace)
168 throw new XmlSchemaException ("The actual targetNamespace in the schema does not match the parameter.");
174 // FIXME: Check the exact behavior when namespaces are in conflict (but it would be preferable to wait for 2.0 RTM)
175 public void Add (XmlSchemaSet schemaSet)
177 ArrayList al = new ArrayList ();
178 foreach (XmlSchema schema in schemaSet.schemas) {
179 if (!schemas.Contains (schema))
182 foreach (XmlSchema schema in al)
186 public XmlSchema Add (XmlSchema schema)
188 schemas.Add (schema);
193 // FIXME: It should be the actual compilation engine.
194 public void Compile ()
196 ClearGlobalComponents ();
197 ArrayList al = new ArrayList ();
198 al.AddRange (schemas);
199 IDCollection.Clear ();
200 NamedIdentities.Clear ();
202 foreach (XmlSchema schema in al)
203 if (!schema.IsCompiled)
204 schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
205 foreach (XmlSchema schema in al)
206 schema.Validate (ValidationEventHandler);
208 foreach (XmlSchema schema in al)
209 AddGlobalComponents (schema);
214 private void ClearGlobalComponents ()
216 GlobalElements.Clear ();
217 GlobalAttributes.Clear ();
218 GlobalTypes.Clear ();
219 // GlobalAttributeGroups.Clear ();
220 // GlobalGroups.Clear ();
223 private void AddGlobalComponents (XmlSchema schema)
225 foreach (XmlSchemaElement el in schema.Elements.Values)
226 GlobalElements.Add (el.QualifiedName, el);
227 foreach (XmlSchemaAttribute a in schema.Attributes.Values)
228 GlobalAttributes.Add (a.QualifiedName, a);
229 foreach (XmlSchemaType t in schema.SchemaTypes.Values)
230 GlobalTypes.Add (t.QualifiedName, t);
233 public bool Contains (string targetNamespace)
235 targetNamespace = GetSafeNs (targetNamespace);
236 foreach (XmlSchema schema in schemas)
237 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
242 public bool Contains (XmlSchema targetNamespace)
244 foreach (XmlSchema schema in schemas)
245 if (schema == targetNamespace)
250 public void CopyTo (XmlSchema [] array, int index)
252 schemas.CopyTo (array, index);
255 internal void CopyTo (Array array, int index)
257 schemas.CopyTo (array, index);
260 string GetSafeNs (string ns)
262 return ns == null ? "" : ns;
266 // FIXME: Check exact behavior
267 public XmlSchema Remove (XmlSchema schema)
270 throw new ArgumentNullException ("schema");
271 ArrayList al = new ArrayList ();
272 al.AddRange (schemas);
273 if (!al.Contains (schema))
275 // FIXME: I have no idea why Remove() might throw
276 // XmlSchemaException, except for the case it compiles.
277 if (!schema.IsCompiled)
278 schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
279 schemas.Remove (schema);
287 ClearGlobalComponents ();
290 public bool RemoveRecursive (XmlSchema schema)
293 throw new ArgumentNullException ("schema");
294 ArrayList al = new ArrayList ();
295 al.AddRange (schemas);
296 if (!al.Contains (schema))
299 schemas.Remove (schema);
304 ClearGlobalComponents ();
305 foreach (XmlSchema s in al) {
307 AddGlobalComponents (schema);
312 public XmlSchema Reprocess (XmlSchema schema)
315 throw new ArgumentNullException ("schema");
316 ArrayList al = new ArrayList ();
317 al.AddRange (schemas);
318 if (!al.Contains (schema))
319 throw new ArgumentException ("Target schema is not contained in the schema set.");
320 ClearGlobalComponents ();
321 foreach (XmlSchema s in al) {
323 schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
325 AddGlobalComponents (schema);
327 return schema.IsCompiled ? schema : null;
330 public ICollection Schemas ()
335 public ICollection Schemas (string targetNamespace)
337 targetNamespace = GetSafeNs (targetNamespace);
338 ArrayList al = new ArrayList ();
339 foreach (XmlSchema schema in schemas)
340 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
345 internal bool MissedSubComponents (string targetNamespace)
347 foreach (XmlSchema s in Schemas (targetNamespace))
348 if (s.missedSubComponents)