1 //------------------------------------------------------------------------------
2 // <copyright file="SchemaInfo.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 //------------------------------------------------------------------------------
10 using System.Diagnostics;
11 using System.Collections.Generic;
13 namespace System.Xml.Schema {
16 internal enum AttributeMatchState {
19 UndeclaredElementAndAttribute,
23 ProhibitedAnyAttribute,
25 AttributeNameMismatch,
26 ValidateAttributeInvalidCall,
30 internal class SchemaInfo : IDtdInfo {
31 Dictionary<XmlQualifiedName, SchemaElementDecl> elementDecls = new Dictionary<XmlQualifiedName, SchemaElementDecl>();
32 Dictionary<XmlQualifiedName, SchemaElementDecl> undeclaredElementDecls = new Dictionary<XmlQualifiedName, SchemaElementDecl>();
34 Dictionary<XmlQualifiedName, SchemaEntity> generalEntities;
35 Dictionary<XmlQualifiedName, SchemaEntity> parameterEntities;
37 XmlQualifiedName docTypeName = XmlQualifiedName.Empty;
38 string internalDtdSubset = string.Empty;
39 bool hasNonCDataAttributes = false;
40 bool hasDefaultAttributes = false;
43 Dictionary<string, bool> targetNamespaces = new Dictionary<string, bool>();
44 Dictionary<XmlQualifiedName, SchemaAttDef> attributeDecls = new Dictionary<XmlQualifiedName, SchemaAttDef>();
46 SchemaType schemaType;
47 Dictionary<XmlQualifiedName, SchemaElementDecl> elementDeclsByType = new Dictionary<XmlQualifiedName, SchemaElementDecl>();
48 Dictionary<string, SchemaNotation> notations;
52 internal SchemaInfo() {
54 schemaType = SchemaType.None;
58 public XmlQualifiedName DocTypeName {
59 get { return docTypeName; }
60 set { docTypeName = value; }
63 internal string InternalDtdSubset {
64 get { return internalDtdSubset; }
65 set { internalDtdSubset = value; }
68 internal Dictionary<XmlQualifiedName, SchemaElementDecl> ElementDecls {
69 get { return elementDecls; }
72 internal Dictionary<XmlQualifiedName, SchemaElementDecl> UndeclaredElementDecls {
73 get { return undeclaredElementDecls; }
76 internal Dictionary<XmlQualifiedName, SchemaEntity> GeneralEntities {
78 if (this.generalEntities == null) {
79 this.generalEntities = new Dictionary<XmlQualifiedName, SchemaEntity>();
81 return this.generalEntities;
85 internal Dictionary<XmlQualifiedName, SchemaEntity> ParameterEntities {
87 if (this.parameterEntities == null) {
88 this.parameterEntities = new Dictionary<XmlQualifiedName, SchemaEntity>();
90 return this.parameterEntities;
95 internal SchemaType SchemaType {
96 get { return schemaType;}
97 set { schemaType = value;}
100 internal Dictionary<string, bool> TargetNamespaces {
101 get { return targetNamespaces; }
104 internal Dictionary<XmlQualifiedName, SchemaElementDecl> ElementDeclsByType {
105 get { return elementDeclsByType; }
108 internal Dictionary<XmlQualifiedName, SchemaAttDef> AttributeDecls {
109 get { return attributeDecls; }
112 internal Dictionary<string, SchemaNotation> Notations {
114 if (this.notations == null) {
115 this.notations = new Dictionary<string, SchemaNotation>();
117 return this.notations;
121 internal int ErrorCount {
122 get { return errorCount; }
123 set { errorCount = value; }
126 internal SchemaElementDecl GetElementDecl(XmlQualifiedName qname) {
127 SchemaElementDecl elemDecl;
128 if (elementDecls.TryGetValue(qname, out elemDecl)) {
134 internal SchemaElementDecl GetTypeDecl(XmlQualifiedName qname) {
135 SchemaElementDecl elemDecl;
136 if (elementDeclsByType.TryGetValue(qname, out elemDecl)) {
143 internal XmlSchemaElement GetElement(XmlQualifiedName qname) {
144 SchemaElementDecl ed = GetElementDecl(qname);
146 return ed.SchemaElement;
151 internal XmlSchemaAttribute GetAttribute(XmlQualifiedName qname) {
152 SchemaAttDef attdef = (SchemaAttDef)attributeDecls[qname];
153 if (attdef != null) {
154 return attdef.SchemaAttribute;
159 internal XmlSchemaElement GetType(XmlQualifiedName qname) {
160 SchemaElementDecl ed = GetElementDecl(qname);
162 return ed.SchemaElement;
167 internal bool HasSchema(string ns) {
168 return targetNamespaces.ContainsKey(ns);
171 internal bool Contains(string ns) {
172 return targetNamespaces.ContainsKey(ns);
175 internal SchemaAttDef GetAttributeXdr(SchemaElementDecl ed, XmlQualifiedName qname) {
176 SchemaAttDef attdef = null;
178 attdef = ed.GetAttDef(qname);;
179 if (attdef == null) {
180 if (!ed.ContentValidator.IsOpen || qname.Namespace.Length == 0) {
181 throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, qname.ToString());
183 if (!attributeDecls.TryGetValue(qname, out attdef) && targetNamespaces.ContainsKey(qname.Namespace)) {
184 throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, qname.ToString());
192 internal SchemaAttDef GetAttributeXsd(SchemaElementDecl ed, XmlQualifiedName qname, XmlSchemaObject partialValidationType, out AttributeMatchState attributeMatchState) {
193 SchemaAttDef attdef = null;
194 attributeMatchState = AttributeMatchState.UndeclaredAttribute;
196 attdef = ed.GetAttDef(qname);
197 if (attdef != null) {
198 attributeMatchState = AttributeMatchState.AttributeFound;
201 XmlSchemaAnyAttribute any = ed.AnyAttribute;
203 if (!any.NamespaceList.Allows(qname)) {
204 attributeMatchState = AttributeMatchState.ProhibitedAnyAttribute;
206 else if (any.ProcessContentsCorrect != XmlSchemaContentProcessing.Skip) {
207 if (attributeDecls.TryGetValue(qname, out attdef)) {
208 if (attdef.Datatype.TypeCode == XmlTypeCode.Id) { //anyAttribute match whose type is ID
209 attributeMatchState = AttributeMatchState.AnyIdAttributeFound;
212 attributeMatchState = AttributeMatchState.AttributeFound;
215 else if (any.ProcessContentsCorrect == XmlSchemaContentProcessing.Lax) {
216 attributeMatchState = AttributeMatchState.AnyAttributeLax;
220 attributeMatchState = AttributeMatchState.AnyAttributeSkip;
223 else if (ed.ProhibitedAttributes.ContainsKey(qname)) {
224 attributeMatchState = AttributeMatchState.ProhibitedAttribute;
227 else if (partialValidationType != null) {
228 XmlSchemaAttribute attr = partialValidationType as XmlSchemaAttribute;
230 if (qname.Equals(attr.QualifiedName)) {
231 attdef = attr.AttDef;
232 attributeMatchState = AttributeMatchState.AttributeFound;
235 attributeMatchState = AttributeMatchState.AttributeNameMismatch;
239 attributeMatchState = AttributeMatchState.ValidateAttributeInvalidCall;
243 if (attributeDecls.TryGetValue(qname, out attdef)) {
244 attributeMatchState = AttributeMatchState.AttributeFound;
247 attributeMatchState = AttributeMatchState.UndeclaredElementAndAttribute;
253 internal SchemaAttDef GetAttributeXsd(SchemaElementDecl ed, XmlQualifiedName qname, ref bool skip) {
254 AttributeMatchState attributeMatchState;
256 SchemaAttDef attDef = GetAttributeXsd(ed, qname, null, out attributeMatchState);
257 switch(attributeMatchState) {
258 case AttributeMatchState.UndeclaredAttribute:
259 throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, qname.ToString());
261 case AttributeMatchState.ProhibitedAnyAttribute:
262 case AttributeMatchState.ProhibitedAttribute:
263 throw new XmlSchemaException(Res.Sch_ProhibitedAttribute, qname.ToString());
265 case AttributeMatchState.AttributeFound:
266 case AttributeMatchState.AnyIdAttributeFound:
267 case AttributeMatchState.AnyAttributeLax:
268 case AttributeMatchState.UndeclaredElementAndAttribute:
271 case AttributeMatchState.AnyAttributeSkip:
282 internal void Add(SchemaInfo sinfo, ValidationEventHandler eventhandler) {
283 if (schemaType == SchemaType.None) {
284 schemaType = sinfo.SchemaType;
286 else if (schemaType != sinfo.SchemaType) {
287 if (eventhandler != null) {
288 eventhandler(this, new ValidationEventArgs(new XmlSchemaException(Res.Sch_MixSchemaTypes, string.Empty)));
293 foreach(string tns in sinfo.TargetNamespaces.Keys) {
294 if (!targetNamespaces.ContainsKey(tns)) {
295 targetNamespaces.Add(tns, true);
299 foreach(KeyValuePair<XmlQualifiedName, SchemaElementDecl> entry in sinfo.elementDecls) {
300 if (!elementDecls.ContainsKey(entry.Key)) {
301 elementDecls.Add(entry.Key, entry.Value);
304 foreach(KeyValuePair<XmlQualifiedName, SchemaElementDecl> entry in sinfo.elementDeclsByType) {
305 if (!elementDeclsByType.ContainsKey(entry.Key)) {
306 elementDeclsByType.Add(entry.Key, entry.Value);
309 foreach (SchemaAttDef attdef in sinfo.AttributeDecls.Values) {
310 if (!attributeDecls.ContainsKey(attdef.Name)) {
311 attributeDecls.Add(attdef.Name, attdef);
314 foreach (SchemaNotation notation in sinfo.Notations.Values) {
315 if (!Notations.ContainsKey(notation.Name.Name)) {
316 Notations.Add(notation.Name.Name, notation);
323 internal void Finish() {
324 Dictionary<XmlQualifiedName, SchemaElementDecl> elements = elementDecls;
325 for ( int i = 0; i < 2; i++ ) {
326 foreach ( SchemaElementDecl e in elements.Values ) {
327 if ( e.HasNonCDataAttribute ) {
328 hasNonCDataAttributes = true;
330 if ( e.DefaultAttDefs != null ) {
331 hasDefaultAttributes = true;
334 elements = undeclaredElementDecls;
338 // IDtdInfo interface
340 #region IDtdInfo Members
341 bool IDtdInfo.HasDefaultAttributes {
343 return hasDefaultAttributes;
347 bool IDtdInfo.HasNonCDataAttributes {
349 return hasNonCDataAttributes;
353 IDtdAttributeListInfo IDtdInfo.LookupAttributeList(string prefix, string localName) {
354 XmlQualifiedName qname = new XmlQualifiedName(prefix, localName);
355 SchemaElementDecl elementDecl;
356 if (!elementDecls.TryGetValue(qname, out elementDecl)) {
357 undeclaredElementDecls.TryGetValue(qname, out elementDecl);
362 IEnumerable<IDtdAttributeListInfo> IDtdInfo.GetAttributeLists() {
363 foreach (SchemaElementDecl elemDecl in elementDecls.Values) {
364 IDtdAttributeListInfo eleDeclAsAttList = (IDtdAttributeListInfo)elemDecl;
365 yield return eleDeclAsAttList;
369 IDtdEntityInfo IDtdInfo.LookupEntity(string name) {
370 if (generalEntities == null) {
373 XmlQualifiedName qname = new XmlQualifiedName(name);
375 if (generalEntities.TryGetValue(qname, out entity)) {
381 XmlQualifiedName IDtdInfo.Name {
382 get { return docTypeName; }
385 string IDtdInfo.InternalDtdSubset {
386 get { return internalDtdSubset; }