// // Mono.Xml.Schema.XsdWildcard.cs // // Author: // Atsushi Enomoto (ginga@kit.hi-ho.ne.jp) // // (C)2003 Atsushi Enomoto // // // This class represents common part of xs:any and xs:anyAttribute // // // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Specialized; using System.Xml; using System.Xml.Schema; namespace Mono.Xml.Schema { internal class XsdWildcard { public XsdWildcard (XmlSchemaObject wildcard) { xsobj = wildcard; } private XmlSchemaObject xsobj; public XmlSchemaContentProcessing ResolvedProcessing; public string TargetNamespace; public bool SkipCompile; public bool HasValueAny; public bool HasValueLocal; public bool HasValueOther; public bool HasValueTargetNamespace; public StringCollection ResolvedNamespaces; void Reset () { HasValueAny = false; HasValueLocal = false; HasValueOther = false; HasValueTargetNamespace = false; ResolvedNamespaces = new StringCollection (); } public void Compile (string nss, ValidationEventHandler h, XmlSchema schema) { if (SkipCompile) return; // used by XmlSchemaAny.AnyTypeContent. Reset (); int nscount = 0; string actualNamespace = nss == null ? "##any" : nss; string[] nslist = XmlSchemaUtil.SplitList(actualNamespace); for (int i = 0; i < nslist.Length; i++) { string ns = nslist [i]; switch(ns) { case "##any": if (HasValueAny) xsobj.error (h, "Multiple specification of ##any was found."); nscount |= 1; HasValueAny = true; break; case "##other": if (HasValueOther) xsobj.error (h, "Multiple specification of ##other was found."); nscount |= 2; HasValueOther = true; break; case "##targetNamespace": if (HasValueTargetNamespace) xsobj.error (h, "Multiple specification of ##targetNamespace was found."); nscount |= 4; HasValueTargetNamespace = true; break; case "##local": if (HasValueLocal) xsobj.error (h, "Multiple specification of ##local was found."); nscount |= 8; HasValueLocal = true; break; default: if(!XmlSchemaUtil.CheckAnyUri(ns)) xsobj.error(h,"the namespace is not a valid anyURI"); else if (ResolvedNamespaces.Contains (ns)) xsobj.error (h, "Multiple specification of '" + ns + "' was found."); else { nscount |= 16; ResolvedNamespaces.Add (ns); } break; } } if((nscount&1) == 1 && nscount != 1) xsobj.error (h, "##any if present must be the only namespace attribute"); if((nscount&2) == 2 && nscount != 2) xsobj.error (h, "##other if present must be the only namespace attribute"); } // 3.8.6. Attribute Wildcard Intersection // Only try to examine if their intersection is expressible, and // returns true if the result is empty. public bool ExamineAttributeWildcardIntersection (XmlSchemaAny other, ValidationEventHandler h, XmlSchema schema) { // 1. if (this.HasValueAny == other.HasValueAny && this.HasValueLocal == other.HasValueLocal && this.HasValueOther == other.HasValueOther && this.HasValueTargetNamespace == other.HasValueTargetNamespace && this.ResolvedProcessing == other.ResolvedProcessContents) { bool notEqual = false; for (int i = 0; i < this.ResolvedNamespaces.Count; i++) { if (!other.ResolvedNamespaces.Contains (this.ResolvedNamespaces [i])) notEqual = true; } if (!notEqual) return false; } // 2. if (this.HasValueAny) return !other.HasValueAny && !other.HasValueLocal && !other.HasValueOther && !other.HasValueTargetNamespace && other.ResolvedNamespaces.Count == 0; if (other.HasValueAny) return !this.HasValueAny && !this.HasValueLocal && !this.HasValueOther && !this.HasValueTargetNamespace && this.ResolvedNamespaces.Count == 0; // 5. if (this.HasValueOther && other.HasValueOther && this.TargetNamespace != other.TargetNamespace) { // xsobj.error (h, "The Wildcard intersection is not expressible."); return false; } // 3. if (this.HasValueOther) { if (other.HasValueLocal && this.TargetNamespace != String.Empty) return false; if (other.HasValueTargetNamespace && this.TargetNamespace != other.TargetNamespace) return false; return other.ValidateWildcardAllowsNamespaceName (this.TargetNamespace, h, schema, false); } if (other.HasValueOther) { if (this.HasValueLocal && other.TargetNamespace != String.Empty) return false; if (this.HasValueTargetNamespace && other.TargetNamespace != this.TargetNamespace) return false; return this.ValidateWildcardAllowsNamespaceName (other.TargetNamespace, h, schema, false); } // 4. if (this.ResolvedNamespaces.Count > 0) { for (int i = 0; i < this.ResolvedNamespaces.Count; i++) if (other.ResolvedNamespaces.Contains (this.ResolvedNamespaces [i])) return false; } return true; } // 3.10.4 Wildcard Allows Namespace Name. (In fact it is almost copy...) public bool ValidateWildcardAllowsNamespaceName (string ns, ValidationEventHandler h, XmlSchema schema, bool raiseError) { if (HasValueAny) return true; if (HasValueOther && ns != TargetNamespace) return true; if (HasValueTargetNamespace && ns == TargetNamespace) return true; if (HasValueLocal && ns == "") return true; for (int i = 0; i < ResolvedNamespaces.Count; i++) if (ns == ResolvedNamespaces [i]) return true; if (raiseError) xsobj.error (h, "This wildcard does not allow the namespace: " + ns); return false; } // 3.10.6 Wildcard Subset // Other = wider. this = restricted subset internal void ValidateWildcardSubset (XsdWildcard other, ValidationEventHandler h, XmlSchema schema) { ValidateWildcardSubset (other, h, schema, true); } internal bool ValidateWildcardSubset (XsdWildcard other, ValidationEventHandler h, XmlSchema schema, bool raiseError) { // 1. if (other.HasValueAny) return true; // 2. if (HasValueOther && other.HasValueOther) { // 2.1 and 2.2 if (TargetNamespace == other.TargetNamespace || other.TargetNamespace == null || other.TargetNamespace == "") return true; } // 3.1. (not) if (this.HasValueAny) { if (raiseError) xsobj.error (h, "Invalid wildcard subset was found."); return false; } // 3.2 if (other.HasValueOther) { // 3.2.2 if ( (this.HasValueTargetNamespace && other.TargetNamespace == this.TargetNamespace) || (this.HasValueLocal && (other.TargetNamespace == null || other.TargetNamespace.Length == 0)) ) { if (raiseError) xsobj.error (h, "Invalid wildcard subset was found."); return false; } else { for (int i = 0; i < ResolvedNamespaces.Count; i++) { if (ResolvedNamespaces [i] == other.TargetNamespace) { if (raiseError) xsobj.error (h, "Invalid wildcard subset was found."); return false; } } } } else { // 3.2.1 if ((this.HasValueLocal && !other.HasValueLocal) || this.HasValueTargetNamespace && !other.HasValueTargetNamespace) { if (raiseError) xsobj.error (h, "Invalid wildcard subset was found."); return false; } else if (this.HasValueOther) { if (raiseError) xsobj.error (h, "Invalid wildcard subset was found."); return false; } else { for (int i = 0; i < this.ResolvedNamespaces.Count; i++) if (!other.ResolvedNamespaces.Contains (this.ResolvedNamespaces [i])) { if (raiseError) xsobj.error (h, "Invalid wildcard subset was found."); return false; } } } return true; } } }