Jo Shields 3c1f479b9d Imported Upstream version 4.0.0~alpha1
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
2015-04-07 09:35:12 +01:00

349 lines
9.7 KiB
C#

//
// XmlSchemaSet.cs
//
// Author:
// Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
//
// (C)2003 Atsushi Enomoto
// (C)2004 Novell Inc.
//
//
// 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;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Security.Policy;
using System.Xml.Schema;
using System.Xml.XPath;
namespace System.Xml.Schema
{
public class XmlSchemaSet
{
XmlNameTable nameTable;
XmlResolver xmlResolver = new XmlUrlResolver ();
ArrayList schemas;
XmlSchemaObjectTable attributes;
XmlSchemaObjectTable elements;
XmlSchemaObjectTable types;
XmlSchemaCompilationSettings settings =
new XmlSchemaCompilationSettings ();
bool isCompiled;
internal Guid CompilationId { get; private set; }
public XmlSchemaSet ()
: this (new NameTable ())
{
}
public XmlSchemaSet (XmlNameTable nameTable)
{
if (nameTable == null)
throw new ArgumentNullException ("nameTable");
this.nameTable = nameTable;
schemas = new ArrayList ();
CompilationId = Guid.NewGuid ();
}
public event ValidationEventHandler ValidationEventHandler;
public int Count {
get { return schemas.Count; }
}
public XmlSchemaObjectTable GlobalAttributes {
get {
if (attributes == null)
attributes = new XmlSchemaObjectTable ();
return attributes;
}
}
public XmlSchemaObjectTable GlobalElements {
get {
if (elements == null)
elements = new XmlSchemaObjectTable ();
return elements;
}
}
public XmlSchemaObjectTable GlobalTypes {
get {
if (types == null)
types = new XmlSchemaObjectTable ();
return types;
}
}
public bool IsCompiled {
get { return isCompiled; }
}
public XmlNameTable NameTable {
get { return nameTable; }
}
public XmlSchemaCompilationSettings CompilationSettings {
get { return settings; }
set { settings = value; }
}
public XmlResolver XmlResolver {
set { xmlResolver = value; }
internal get { return xmlResolver; }
}
public XmlSchema Add (string targetNamespace, string schemaUri)
{
var uri = xmlResolver.ResolveUri (null, schemaUri);
using (var stream = (Stream) xmlResolver.GetEntity (uri, null, typeof (Stream)))
using (var r = XmlReader.Create (stream, new XmlReaderSettings () { XmlResolver = xmlResolver, NameTable = nameTable}, uri.ToString ()))
return Add (targetNamespace, r);
}
public XmlSchema Add (string targetNamespace, XmlReader schemaDocument)
{
XmlSchema schema = XmlSchema.Read (schemaDocument, ValidationEventHandler);
if (schema.TargetNamespace == null)
schema.TargetNamespace = targetNamespace == String.Empty ? null : targetNamespace; // this weirdness is due to bug #571660.
else if (targetNamespace != null && schema.TargetNamespace != targetNamespace)
throw new XmlSchemaException ("The actual targetNamespace in the schema does not match the parameter.");
Add (schema);
return schema;
}
[MonoTODO]
// FIXME: Check the exact behavior when namespaces are in conflict (but it would be preferable to wait for 2.0 RTM)
public void Add (XmlSchemaSet schemas)
{
ArrayList al = new ArrayList ();
foreach (XmlSchema schema in schemas.schemas) {
if (!this.schemas.Contains (schema))
al.Add (schema);
}
foreach (XmlSchema schema in al)
Add (schema);
}
public XmlSchema Add (XmlSchema schema)
{
schemas.Add (schema);
ResetCompile ();
return schema;
}
// FIXME: It should be the actual compilation engine.
public void Compile ()
{
ClearGlobalComponents ();
ArrayList al = new ArrayList ();
al.AddRange (schemas);
var handledUris = new List<CompiledSchemaMemo> ();
foreach (XmlSchema schema in al)
if (!schema.IsCompiled)
schema.CompileSubset (ValidationEventHandler, this, xmlResolver, handledUris);
// Process substitutionGroup first, as this process
// involves both substituted and substituting elements
// and hence it needs to be done before actual
// validation (by current design of conformance checker).
foreach (XmlSchema schema in al)
foreach (XmlSchemaElement elem in schema.Elements.Values)
elem.FillSubstitutionElementInfo ();
foreach (XmlSchema schema in al)
schema.Validate (ValidationEventHandler);
foreach (XmlSchema schema in al)
AddGlobalComponents (schema);
isCompiled = true;
}
private void ClearGlobalComponents ()
{
GlobalElements.Clear ();
GlobalAttributes.Clear ();
GlobalTypes.Clear ();
global_attribute_groups.Clear ();
global_groups.Clear ();
global_notations.Clear ();
global_ids.Clear ();
global_identity_constraints.Clear ();
}
XmlSchemaObjectTable global_attribute_groups = new XmlSchemaObjectTable ();
XmlSchemaObjectTable global_groups = new XmlSchemaObjectTable ();
XmlSchemaObjectTable global_notations = new XmlSchemaObjectTable ();
XmlSchemaObjectTable global_identity_constraints = new XmlSchemaObjectTable ();
Hashtable global_ids = new Hashtable ();
private void AddGlobalComponents (XmlSchema schema)
{
foreach (XmlSchemaElement el in schema.Elements.Values)
GlobalElements.Add (el.QualifiedName, el);
foreach (XmlSchemaAttribute a in schema.Attributes.Values)
GlobalAttributes.Add (a.QualifiedName, a);
foreach (XmlSchemaType t in schema.SchemaTypes.Values)
GlobalTypes.Add (t.QualifiedName, t);
foreach (XmlSchemaAttributeGroup g in schema.AttributeGroups.Values)
global_attribute_groups.Add (g.QualifiedName, g);
foreach (XmlSchemaGroup g in schema.Groups.Values)
global_groups.Add (g.QualifiedName, g);
foreach (DictionaryEntry pair in schema.IDCollection)
global_ids.Add (pair.Key, pair.Value);
foreach (XmlSchemaIdentityConstraint ic in schema.NamedIdentities.Values)
global_identity_constraints.Add (ic.QualifiedName, ic);
}
public bool Contains (string targetNamespace)
{
targetNamespace = GetSafeNs (targetNamespace);
foreach (XmlSchema schema in schemas)
if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
return true;
return false;
}
public bool Contains (XmlSchema schema)
{
foreach (XmlSchema s in schemas)
if (s == schema)
return true;
return false;
}
public void CopyTo (XmlSchema [] schemas, int index)
{
this.schemas.CopyTo (schemas, index);
}
internal void CopyTo (Array array, int index)
{
schemas.CopyTo (array, index);
}
string GetSafeNs (string ns)
{
return ns == null ? "" : ns;
}
[MonoTODO]
// FIXME: Check exact behavior
public XmlSchema Remove (XmlSchema schema)
{
if (schema == null)
throw new ArgumentNullException ("schema");
ArrayList al = new ArrayList ();
al.AddRange (schemas);
if (!al.Contains (schema))
return null;
// FIXME: I have no idea why Remove() might throw
// XmlSchemaException, except for the case it compiles.
if (!schema.IsCompiled)
schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
schemas.Remove (schema);
ResetCompile ();
return schema;
}
void ResetCompile ()
{
isCompiled = false;
ClearGlobalComponents ();
}
public bool RemoveRecursive (XmlSchema schemaToRemove)
{
if (schemaToRemove == null)
throw new ArgumentNullException ("schema");
ArrayList al = new ArrayList ();
al.AddRange (schemas);
if (!al.Contains (schemaToRemove))
return false;
al.Remove (schemaToRemove);
schemas.Remove (schemaToRemove);
if (!IsCompiled)
return true;
ClearGlobalComponents ();
foreach (XmlSchema s in al) {
if (s.IsCompiled)
AddGlobalComponents (schemaToRemove);
}
return true;
}
public XmlSchema Reprocess (XmlSchema schema)
{
if (schema == null)
throw new ArgumentNullException ("schema");
ArrayList al = new ArrayList ();
al.AddRange (schemas);
if (!al.Contains (schema))
throw new ArgumentException ("Target schema is not contained in the schema set.");
ClearGlobalComponents ();
foreach (XmlSchema s in al) {
if (schema == s)
schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
if (s.IsCompiled)
AddGlobalComponents (schema);
}
return schema.IsCompiled ? schema : null;
}
public ICollection Schemas ()
{
return schemas;
}
public ICollection Schemas (string targetNamespace)
{
targetNamespace = GetSafeNs (targetNamespace);
ArrayList al = new ArrayList ();
foreach (XmlSchema schema in schemas)
if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
al.Add (schema);
return al;
}
internal bool MissedSubComponents (string targetNamespace)
{
foreach (XmlSchema s in Schemas (targetNamespace))
if (s.missedSubComponents)
return true;
return false;
}
}
}