SchemaHelper.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //----------------------------------------------------------------------------
  4. namespace System.ServiceModel.Description
  5. {
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using System.Collections.ObjectModel;
  9. using System.Runtime;
  10. using System.Xml;
  11. using System.Xml.Schema;
  12. static class SchemaHelper
  13. {
  14. static internal void AddElementForm(XmlSchemaElement element, XmlSchema schema)
  15. {
  16. if (schema.ElementFormDefault != XmlSchemaForm.Qualified)
  17. element.Form = XmlSchemaForm.Qualified;
  18. }
  19. static internal void AddElementToSchema(XmlSchemaElement element, XmlSchema schema, XmlSchemaSet schemaSet)
  20. {
  21. XmlSchemaElement existingElement = (XmlSchemaElement)schema.Elements[new XmlQualifiedName(element.Name, schema.TargetNamespace)];
  22. if (existingElement != null)
  23. {
  24. if (element.SchemaType == existingElement.SchemaType && element.SchemaTypeName == existingElement.SchemaTypeName)
  25. return;
  26. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxConflictingGlobalElement, element.Name, schema.TargetNamespace, GetTypeName(element), GetTypeName(existingElement))));
  27. }
  28. schema.Items.Add(element);
  29. if (!element.SchemaTypeName.IsEmpty)
  30. AddImportToSchema(element.SchemaTypeName.Namespace, schema);
  31. schemaSet.Reprocess(schema);
  32. }
  33. static internal void AddImportToSchema(string ns, XmlSchema schema)
  34. {
  35. if (NamespacesEqual(ns, schema.TargetNamespace)
  36. || NamespacesEqual(ns, XmlSchema.Namespace)
  37. || NamespacesEqual(ns, XmlSchema.InstanceNamespace))
  38. return;
  39. foreach (object item in schema.Includes)
  40. {
  41. if (item is XmlSchemaImport && NamespacesEqual(ns, ((XmlSchemaImport)item).Namespace))
  42. return;
  43. }
  44. XmlSchemaImport import = new XmlSchemaImport();
  45. if (ns != null && ns.Length > 0)
  46. import.Namespace = ns;
  47. schema.Includes.Add(import);
  48. }
  49. static internal void AddTypeToSchema(XmlSchemaType type, XmlSchema schema, XmlSchemaSet schemaSet)
  50. {
  51. XmlSchemaType existingType = (XmlSchemaType)schema.SchemaTypes[new XmlQualifiedName(type.Name, schema.TargetNamespace)];
  52. if (existingType != null)
  53. {
  54. if (existingType == type)
  55. return;
  56. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxConflictingGlobalType, type.Name, schema.TargetNamespace)));
  57. }
  58. schema.Items.Add(type);
  59. schemaSet.Reprocess(schema);
  60. }
  61. static internal XmlSchema GetSchema(string ns, XmlSchemaSet schemaSet)
  62. {
  63. if (ns == null) { ns = String.Empty; }
  64. ICollection schemas = schemaSet.Schemas();
  65. foreach (XmlSchema existingSchema in schemas)
  66. {
  67. if ((existingSchema.TargetNamespace == null && ns.Length == 0) || ns.Equals(existingSchema.TargetNamespace))
  68. return existingSchema;
  69. }
  70. XmlSchema schema = new XmlSchema();
  71. schema.ElementFormDefault = XmlSchemaForm.Qualified;
  72. if (ns.Length > 0)
  73. schema.TargetNamespace = ns;
  74. schemaSet.Add(schema);
  75. return schema;
  76. }
  77. static string GetTypeName(XmlSchemaElement element)
  78. {
  79. if (element.SchemaType != null)
  80. return "anonymous";
  81. if (!element.SchemaTypeName.IsEmpty)
  82. return element.SchemaTypeName.ToString();
  83. return String.Empty;
  84. }
  85. // Compare XmlSchemaElement properties set by WsdlExporter: do not check element QName,
  86. // this code only called for elements with matching name and namespace
  87. internal static bool IsMatch(XmlSchemaElement e1, XmlSchemaElement e2)
  88. {
  89. // this code only called for elements with matching name and namespace
  90. Fx.Assert(e1.Name == e2.Name, "");
  91. // Anonymous types never match
  92. if (e1.SchemaType != null || e2.SchemaType != null)
  93. return false;
  94. if (e1.SchemaTypeName != e2.SchemaTypeName)
  95. return false;
  96. // do not need to check parent Schema.ElementFormDefault: see AddElementForm in this class.
  97. if (e1.Form != e2.Form)
  98. return false;
  99. if (e1.IsNillable != e2.IsNillable)
  100. return false;
  101. return true;
  102. }
  103. static internal bool NamespacesEqual(string ns1, string ns2)
  104. {
  105. if (ns1 == null || ns1.Length == 0)
  106. return (ns2 == null || ns2.Length == 0);
  107. else
  108. return ns1 == ns2;
  109. }
  110. static internal void Compile(XmlSchemaSet schemaSet, Collection<MetadataConversionError> errors)
  111. {
  112. ValidationEventHandler validationEventHandler = new ValidationEventHandler(delegate(object sender, ValidationEventArgs args)
  113. {
  114. HandleSchemaValidationError(sender, args, errors);
  115. }
  116. );
  117. schemaSet.ValidationEventHandler += validationEventHandler;
  118. schemaSet.Compile();
  119. schemaSet.ValidationEventHandler -= validationEventHandler;
  120. }
  121. static internal void HandleSchemaValidationError(object sender, ValidationEventArgs args, Collection<MetadataConversionError> errors)
  122. {
  123. MetadataConversionError warning = null;
  124. if (args.Exception != null && args.Exception.SourceUri != null)
  125. {
  126. XmlSchemaException ex = args.Exception;
  127. warning = new MetadataConversionError(SR.GetString(SR.SchemaValidationError, ex.SourceUri, ex.LineNumber, ex.LinePosition, ex.Message));
  128. }
  129. else
  130. {
  131. warning = new MetadataConversionError(SR.GetString(SR.GeneralSchemaValidationError, args.Message));
  132. }
  133. if (!errors.Contains(warning))
  134. errors.Add(warning);
  135. }
  136. static IList<string> xsdValueTypePrimitives = new string[]
  137. {
  138. "boolean", "float", "double", "decimal", "long", "unsignedLong", "int", "unsignedInt", "short", "unsignedShort", "byte", "unsignedByte",
  139. "duration", "dateTime", "integer", "positiveInteger", "negativeInteger", "nonPositiveInteger"
  140. };
  141. static IList<string> dataContractPrimitives = new string[]
  142. {
  143. "char", "guid"
  144. };
  145. static IList<string> xmlSerializerPrimitives = new string[]
  146. {
  147. "char", "guid"
  148. };
  149. static string dataContractSerializerNamespace = "http://schemas.microsoft.com/2003/10/Serialization/";
  150. static string xmlSerializerNamespace = "http://microsoft.com/wsdl/types/";
  151. internal static bool IsElementValueType(XmlSchemaElement element)
  152. {
  153. XmlQualifiedName typeName = element.SchemaTypeName;
  154. if (typeName == null || typeName.IsEmpty)
  155. return false;
  156. if (typeName.Namespace == XmlSchema.Namespace)
  157. return xsdValueTypePrimitives.Contains(typeName.Name);
  158. if (typeName.Namespace == dataContractSerializerNamespace)
  159. return dataContractPrimitives.Contains(typeName.Name);
  160. if (typeName.Namespace == xmlSerializerNamespace)
  161. return dataContractPrimitives.Contains(typeName.Name);
  162. return false;
  163. }
  164. }
  165. }